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 Sep 29 2013
10 	copyright            : (C) 2013 by Franz Schmid
11 	email                : Franz.Schmid@altmuehlnet.de
12  ***************************************************************************/
13 
14 #include <QByteArray>
15 #include <QCursor>
16 #include <QDrag>
17 #include <QFile>
18 #include <QList>
19 #include <QMimeData>
20 #include <QRegExp>
21 #include <QStack>
22 #include <QUrl>
23 #include <QDebug>
24 
25 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
26 #define _USE_MATH_DEFINES
27 #endif
28 
29 #include <cstdlib>
30 #include <climits>
31 #include <limits>
32 
33 
34 #include "importviva.h"
35 
36 
37 
38 #include "commonstrings.h"
39 #include "loadsaveplugin.h"
40 #include "pageitem_table.h"
41 #include "pagesize.h"
42 #include "prefscontext.h"
43 #include "prefsfile.h"
44 #include "prefsmanager.h"
45 #include "prefstable.h"
46 #include "rawimage.h"
47 #include "scclocale.h"
48 #include "sccolorengine.h"
49 #include "scconfig.h"
50 #include "scmimedata.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 "ui/customfdialog.h"
59 #include "ui/missing.h"
60 #include "ui/multiprogressdialog.h"
61 #include "ui/propertiespalette.h"
62 #include "undomanager.h"
63 #include "util.h"
64 #include "util_formats.h"
65 #include "util_math.h"
66 
VivaPlug(ScribusDoc * doc,int flags)67 VivaPlug::VivaPlug(ScribusDoc* doc, int flags)
68 {
69 	tmpSel = new Selection(this, false);
70 	m_Doc = doc;
71 	importerFlags = flags;
72 	interactive = (flags & LoadSavePlugin::lfInteractive);
73 	progressDialog = nullptr;
74 }
75 
parseUnit(const QString & unit)76 double VivaPlug::parseUnit(const QString &unit)
77 {
78 	bool noUnit = false;
79 	QString unitval=unit;
80 	if (unit.right( 2 ) == "pt")
81 		unitval.replace( "pt", "");
82 	else if (unit.right( 2 ) == "cm")
83 		unitval.replace( "cm", "" );
84 	else if (unit.right( 2 ) == "mm")
85 		unitval.replace( "mm" , "");
86 	else if (unit.right( 2 ) == "in")
87 		unitval.replace( "in", "" );
88 	else if (unit.right( 2 ) == "px")
89 		unitval.replace( "px", "" );
90 	if (unitval == unit)
91 		noUnit = true;
92 	double value = ScCLocale::toDoubleC(unitval);
93 	if (unit.right( 2 ) == "pt")
94 		{}/* value = value; */ //no change
95 	else if (unit.right( 2 ) == "cm")
96 		value = ( value / 2.54 ) * 72;
97 	else if (unit.right( 2 ) == "mm")
98 		value = ( value / 25.4 ) * 72;
99 	else if (unit.right( 2 ) == "in")
100 		value = value * 72;
101 	else if (unit.right( 2 ) == "px")
102 		value = value * 0.8;
103 	else if (noUnit)
104 		{}/* value = value; */ //no change
105 	return value;
106 }
107 
readThumbnail(const QString & fName)108 QImage VivaPlug::readThumbnail(const QString& fName)
109 {
110 	QImage tmp;
111 	if ( !QFile::exists(fName) )
112 		return QImage();
113 	progressDialog = nullptr;
114 	QFileInfo fi = QFileInfo(fName);
115 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
116 	docWidth = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
117 	docHeight = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
118 	m_Doc = new ScribusDoc();
119 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
120 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
121 	m_Doc->addPage(0);
122 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
123 	baseX = m_Doc->currentPage()->xOffset();
124 	baseY = m_Doc->currentPage()->yOffset();
125 	Elements.clear();
126 	m_Doc->setLoading(true);
127 	m_Doc->DoDrawing = false;
128 	m_Doc->scMW()->setScriptRunning(true);
129 	QString CurDirP = QDir::currentPath();
130 	QDir::setCurrent(fi.path());
131 	if (convert(fName))
132 	{
133 		tmpSel->clear();
134 		QDir::setCurrent(CurDirP);
135 		if (Elements.count() > 1)
136 			m_Doc->groupObjectsList(Elements);
137 		m_Doc->DoDrawing = true;
138 		m_Doc->m_Selection->delaySignalsOn();
139 		QImage tmpImage;
140 		if (Elements.count() > 0)
141 		{
142 			for (int dre=0; dre<Elements.count(); ++dre)
143 			{
144 				tmpSel->addItem(Elements.at(dre), true);
145 			}
146 			tmpSel->setGroupRect();
147 			double xs = tmpSel->width();
148 			double ys = tmpSel->height();
149 			tmpImage = Elements.at(0)->DrawObj_toImage(500);
150 			tmpImage.setText("XSize", QString("%1").arg(xs));
151 			tmpImage.setText("YSize", QString("%1").arg(ys));
152 		}
153 		m_Doc->scMW()->setScriptRunning(false);
154 		m_Doc->setLoading(false);
155 		m_Doc->m_Selection->delaySignalsOff();
156 		delete m_Doc;
157 		return tmpImage;
158 	}
159 	QDir::setCurrent(CurDirP);
160 	m_Doc->DoDrawing = true;
161 	m_Doc->scMW()->setScriptRunning(false);
162 	delete m_Doc;
163 	return tmp;
164 }
165 
readColors(const QString & fileName,ColorList & colors)166 bool VivaPlug::readColors(const QString& fileName, ColorList & colors)
167 {
168 	bool success = false;
169 	m_Doc = new ScribusDoc();
170 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
171 	m_Doc->setPage(1, 1, 0, 0, 0, 0, 0, 0, false, false);
172 	m_Doc->addPage(0);
173 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
174 	importedColors.clear();
175 	QByteArray f;
176 	loadRawText(fileName, f);
177 	if (designMapDom.setContent(f))
178 	{
179 		QDomElement docElem = designMapDom.documentElement();
180 		for (QDomNode drawPag = docElem.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling() )
181 		{
182 			QDomElement dpg = drawPag.toElement();
183 			if (dpg.tagName() == "vc:colors")
184 				parseColorsXML(dpg);
185 		}
186 	}
187 	if (importedColors.count() != 0)
188 	{
189 		colors = m_Doc->PageColors;
190 		success = true;
191 	}
192 	delete m_Doc;
193 	return success;
194 }
195 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)196 bool VivaPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
197 {
198 	bool success = false;
199 	interactive = (flags & LoadSavePlugin::lfInteractive);
200 	importerFlags = flags;
201 	cancel = false;
202 	bool ret = false;
203 	hasLayers = false;
204 	firstLayer = true;
205 	firstPage = true;
206 	pagecount = 1;
207 	mpagecount = 0;
208 	QFileInfo fi = QFileInfo(fNameIn);
209 	if ( !ScCore->usingGUI() )
210 	{
211 		interactive = false;
212 		showProgress = false;
213 	}
214 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
215 	if ( showProgress )
216 	{
217 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
218 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
219 		QStringList barNames, barTexts;
220 		barNames << "GI";
221 		barTexts << tr("Analyzing File:");
222 		QList<bool> barsNumeric;
223 		barsNumeric << false;
224 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
225 		progressDialog->setOverallTotalSteps(3);
226 		progressDialog->setOverallProgress(0);
227 		progressDialog->setProgress("GI", 0);
228 		progressDialog->show();
229 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
230 		qApp->processEvents();
231 	}
232 	else
233 		progressDialog = nullptr;
234 	if (progressDialog)
235 	{
236 		progressDialog->setOverallProgress(1);
237 		qApp->processEvents();
238 	}
239 	/* Set default Page to size defined in Preferences */
240 	docWidth = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
241 	docHeight = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
242 	baseX = 0;
243 	baseY = 0;
244 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
245 	{
246 		m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
247 		m_Doc->addPage(0);
248 		m_Doc->view()->addPage(0, true);
249 		baseX = 0;
250 		baseY = 0;
251 	}
252 	else
253 	{
254 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
255 		{
256 			m_Doc=ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
257 			ScCore->primaryMainWindow()->HaveNewDoc();
258 			ret = true;
259 			baseX = 0;
260 			baseY = 0;
261 			baseX = m_Doc->currentPage()->xOffset();
262 			baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
263 		}
264 	}
265 	if ((!ret) && (interactive))
266 	{
267 		baseX = m_Doc->currentPage()->xOffset();
268 		baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
269 	}
270 	if ((ret) || (!interactive))
271 	{
272 		if (docWidth > docHeight)
273 			m_Doc->setPageOrientation(1);
274 		else
275 			m_Doc->setPageOrientation(0);
276 		m_Doc->setPageSize("Custom");
277 	}
278 	Elements.clear();
279 	m_Doc->setLoading(true);
280 	m_Doc->DoDrawing = false;
281 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
282 		m_Doc->view()->updatesOn(false);
283 	m_Doc->scMW()->setScriptRunning(true);
284 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
285 	QString CurDirP = QDir::currentPath();
286 	QDir::setCurrent(fi.path());
287 	if (convert(fNameIn))
288 	{
289 		tmpSel->clear();
290 		QDir::setCurrent(CurDirP);
291 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
292 			m_Doc->groupObjectsList(Elements);
293 		m_Doc->DoDrawing = true;
294 		m_Doc->scMW()->setScriptRunning(false);
295 		m_Doc->setLoading(false);
296 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
297 		if ((Elements.count() > 0) && (!ret) && (interactive))
298 		{
299 			if (flags & LoadSavePlugin::lfScripted)
300 			{
301 				bool loadF = m_Doc->isLoading();
302 				m_Doc->setLoading(false);
303 				m_Doc->changed();
304 				m_Doc->setLoading(loadF);
305 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
306 				{
307 					m_Doc->m_Selection->delaySignalsOn();
308 					for (int dre=0; dre<Elements.count(); ++dre)
309 					{
310 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
311 					}
312 					m_Doc->m_Selection->delaySignalsOff();
313 					m_Doc->m_Selection->setGroupRect();
314 					m_Doc->view()->updatesOn(true);
315 				}
316 			}
317 			else
318 			{
319 				m_Doc->DragP = true;
320 				m_Doc->DraggedElem = nullptr;
321 				m_Doc->DragElements.clear();
322 				m_Doc->m_Selection->delaySignalsOn();
323 				for (int dre=0; dre<Elements.count(); ++dre)
324 				{
325 					tmpSel->addItem(Elements.at(dre), true);
326 				}
327 				tmpSel->setGroupRect();
328 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
329 				m_Doc->itemSelection_DeleteItem(tmpSel);
330 				m_Doc->view()->updatesOn(true);
331 				m_Doc->m_Selection->delaySignalsOff();
332 				// We must copy the TransationSettings object as it is owned
333 				// by handleObjectImport method afterwards
334 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
335 				m_Doc->view()->handleObjectImport(md, transacSettings);
336 				m_Doc->DragP = false;
337 				m_Doc->DraggedElem = nullptr;
338 				m_Doc->DragElements.clear();
339 			}
340 		}
341 		else
342 		{
343 			m_Doc->changed();
344 			m_Doc->reformPages();
345 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
346 				m_Doc->view()->updatesOn(true);
347 		}
348 		success = true;
349 	}
350 	else
351 	{
352 		QDir::setCurrent(CurDirP);
353 		m_Doc->DoDrawing = true;
354 		m_Doc->scMW()->setScriptRunning(false);
355 		if (!(flags & LoadSavePlugin::lfLoadAsPattern))
356 			m_Doc->view()->updatesOn(true);
357 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
358 	}
359 	if (interactive)
360 		m_Doc->setLoading(false);
361 	//CB If we have a gui we must refresh it if we have used the progressbar
362 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
363 	{
364 		if ((showProgress) && (!interactive))
365 			m_Doc->view()->DrawNew();
366 	}
367 	qApp->restoreOverrideCursor();
368 	return success;
369 }
370 
~VivaPlug()371 VivaPlug::~VivaPlug()
372 {
373 	delete progressDialog;
374 	delete tmpSel;
375 }
376 
convert(const QString & fn)377 bool VivaPlug::convert(const QString& fn)
378 {
379 	Coords.resize(0);
380 	Coords.svgInit();
381 	importedColors.clear();
382 	facingPages = false;
383 	if (progressDialog)
384 	{
385 		progressDialog->setOverallProgress(2);
386 		progressDialog->setLabel("GI", tr("Generating Items"));
387 		qApp->processEvents();
388 	}
389 	bool retVal = true;
390 	importedColors.clear();
391 	storyMap.clear();
392 	QByteArray f;
393 	loadRawText(fn, f);
394 	if (designMapDom.setContent(f))
395 	{
396 		QDomElement docElem = designMapDom.documentElement();
397 		for (QDomNode drawPag = docElem.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling())
398 		{
399 			QDomElement dpg = drawPag.toElement();
400 			if (dpg.tagName() == "vd:settings")
401 				parseSettingsXML(dpg);
402 			else if (dpg.tagName() == "vc:colors")
403 				parseColorsXML(dpg);
404 			else if (dpg.tagName() == "vs:stylesheets")
405 				parseStylesheetsXML(dpg);
406 			else if (dpg.tagName() == "vd:preferences")
407 				parsePreferencesXML(dpg);
408 			else if (dpg.tagName() == "vd:layer")
409 				parseLayerXML(dpg);
410 			else if (dpg.tagName() == "vd:singleAliasPage")
411 				parseMasterSpreadXML(dpg);
412 			else if (dpg.tagName() == "vd:doubleAliasPage")
413 				parseMasterSpreadXML(dpg);
414 			else if (dpg.tagName() == "vd:spread")
415 				parseSpreadXML(dpg);
416 			else if (dpg.tagName() == "vd:textChains")
417 				parseTextChainsXML(dpg);
418 		}
419 	}
420 	if (progressDialog)
421 		progressDialog->close();
422 	return retVal;
423 }
424 
parseSettingsXML(const QDomElement & grNode)425 void VivaPlug::parseSettingsXML(const QDomElement& grNode)
426 {
427 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
428 	{
429 		topMargin = m_Doc->marginsVal().top();
430 		leftMargin = m_Doc->marginsVal().left();
431 		rightMargin = m_Doc->marginsVal().right();
432 		bottomMargin = m_Doc->marginsVal().bottom();
433 		double pgCols = m_Doc->PageSp;
434 		double pgGap = m_Doc->PageSpa;
435 		papersize = "Custom";
436 		QString paperOrien = "portrait";
437 		bool hasPageSize = false;
438 		for (QDomNode n = grNode.firstChild(); !n.isNull(); n = n.nextSibling() )
439 		{
440 			QDomElement e = n.toElement();
441 			if (e.tagName() == "vd:pageMargins")
442 			{
443 				topMargin = parseUnit(e.attribute("vd:top", "0"));
444 				leftMargin = parseUnit(e.attribute("vd:left", "0"));
445 				rightMargin = parseUnit(e.attribute("vd:right", "0"));
446 				bottomMargin = parseUnit(e.attribute("vd:bottom", "0"));
447 			}
448 			else if (e.tagName() == "vd:pageColumns")
449 			{
450 				pgCols = e.attribute("vd:count", "1").toInt();
451 				pgGap = parseUnit(e.attribute("vd:distance", "0"));
452 			}
453 			else if (e.tagName() == "vd:pageMode")
454 				facingPages = e.text() == "doublePage";
455 			else if (e.tagName() == "vd:pageFormat")
456 				papersize = e.text();
457 			else if (e.tagName() == "vd:pageOrientation")
458 				paperOrien = e.text();
459 			else if (e.tagName() == "vd:pageSize")
460 			{
461 				docWidth = parseUnit(e.attribute("vd:width", "0"));
462 				docHeight = parseUnit(e.attribute("vd:height", "0"));
463 				hasPageSize = true;
464 			}
465 		}
466 		PageSize ps(papersize);
467 		if (hasPageSize)
468 		{
469 			if (!paperOrien.startsWith("portrait"))
470 			{
471 				double tmp = docWidth;
472 				docWidth = docHeight;
473 				docHeight = tmp;
474 			}
475 		}
476 		else
477 		{
478 			if (paperOrien.startsWith("portrait"))
479 			{
480 				docWidth = ps.width();
481 				docHeight = ps.height();
482 			}
483 			else
484 			{
485 				docHeight = ps.width();
486 				docWidth = ps.height();
487 			}
488 		}
489 		m_Doc->setPage(docWidth, docHeight, topMargin, leftMargin, rightMargin, bottomMargin, pgCols, pgGap, false, facingPages);
490 		m_Doc->setPageSize(papersize);
491 		m_Doc->currentPage()->setSize(papersize);
492 		m_Doc->currentPage()->setInitialHeight(docHeight);
493 		m_Doc->currentPage()->setInitialWidth(docWidth);
494 		m_Doc->currentPage()->setHeight(docHeight);
495 		m_Doc->currentPage()->setWidth(docWidth);
496 		m_Doc->currentPage()->initialMargins.setTop(topMargin);
497 		m_Doc->currentPage()->initialMargins.setBottom(bottomMargin);
498 		m_Doc->currentPage()->initialMargins.setLeft(leftMargin);
499 		m_Doc->currentPage()->initialMargins.setRight(rightMargin);
500 		m_Doc->reformPages(true);
501 	}
502 }
503 
parseColorsXML(const QDomElement & grNode)504 void VivaPlug::parseColorsXML(const QDomElement& grNode)
505 {
506 	for (QDomNode n = grNode.firstChild(); !n.isNull(); n = n.nextSibling() )
507 	{
508 		QDomElement e = n.toElement();
509 		if (e.tagName() == "vc:color")
510 		{
511 			QString colorName = e.attribute("vc:name");
512 			if (e.hasChildNodes())
513 			{
514 				bool seenSpot = false;
515 				bool seenRegC = false;
516 				ScColor tmp;
517 				for (QDomNode gr = e.firstChild(); !gr.isNull(); gr = gr.nextSibling() )
518 				{
519 					QDomElement grs = gr.toElement();
520 					if (grs.tagName() == "vc:rgb")
521 					{
522 						int r = grs.attribute("vc:red", "0").toInt();
523 						int g = grs.attribute("vc:green", "0").toInt();
524 						int b = grs.attribute("vc:blue", "0").toInt();
525 						tmp.setRgbColor(r, g, b);
526 						break;
527 					}
528 					if (grs.tagName() == "vc:cmyk")
529 					{
530 						int c = grs.attribute("vc:cyan", "0").toInt();
531 						int m = grs.attribute("vc:magenta", "0").toInt();
532 						int y = grs.attribute("vc:yellow", "0").toInt();
533 						int k = grs.attribute("vc:key", "0").toInt();
534 						tmp.setColor(c, m, y, k);
535 						break;
536 					}
537 					if (grs.tagName() == "vc:lab")
538 					{
539 						double L = grs.attribute("vc:l", "100").toDouble();
540 						double a = grs.attribute("vc:a", "0").toDouble();
541 						double b = grs.attribute("vc:b", "0").toDouble();
542 						tmp.setLabColor(L, a, b);
543 						break;
544 					}
545 					if (grs.tagName() == "vc:hsv")
546 					{
547 						int h = grs.attribute("vc:hue", "0").toInt();
548 						int s = grs.attribute("vc:saturation", "0").toInt();
549 						int v = grs.attribute("vc:value", "0").toInt();
550 						QColor qc;
551 						qc.setHsv(h, s, v);
552 						tmp.fromQColor(qc);
553 						tmp = ScColorEngine::convertToModel(tmp, m_Doc, colorModelRGB);
554 						break;
555 					}
556 					if (grs.tagName() == "vc:registrationColor")
557 					{
558 						seenRegC = true;
559 						int r = e.attribute("vc:red", "0").toInt();
560 						int g = e.attribute("vc:green", "0").toInt();
561 						int b = e.attribute("vc:blue", "0").toInt();
562 						tmp.setRgbColor(r, g, b);
563 						break;
564 					}
565 					if (grs.tagName() == "vc:spotColor")
566 						seenSpot = true;
567 				}
568 				tmp.setSpotColor(seenSpot);
569 				tmp.setRegistrationColor(seenRegC);
570 				QString fNam = m_Doc->PageColors.tryAddColor(colorName, tmp);
571 				if (fNam == colorName)
572 					importedColors.append(fNam);
573 				colorTranslate.insert(colorName, fNam);
574 			}
575 			else
576 			{
577 				int r = e.attribute("vc:red", "0").toInt();
578 				int g = e.attribute("vc:green", "0").toInt();
579 				int b = e.attribute("vc:blue", "0").toInt();
580 				ScColor tmp;
581 				tmp.setRgbColor(r, g, b);
582 				tmp.setSpotColor(false);
583 				tmp.setRegistrationColor(false);
584 				QString fNam = m_Doc->PageColors.tryAddColor(colorName, tmp);
585 				if (fNam == colorName)
586 					importedColors.append(fNam);
587 				colorTranslate.insert(colorName, fNam);
588 			}
589 		}
590 		else if (e.tagName() == "vc:gradient")
591 		{
592 			QString grName = e.attribute("vc:name");
593 			QString grSelf = grName;
594 			int grTyp = 6;
595 			if (e.attribute("vc:type") == "linear")
596 				grTyp =6;
597 			else if (e.attribute("vc:type") == "radial")
598 				grTyp = 7;
599 			else if (e.attribute("vc:type") == "rectangle")
600 				grTyp = 10;
601 			VGradient currentGradient = VGradient(VGradient::linear);
602 			currentGradient.clearStops();
603 			for (QDomNode gr = e.firstChild(); !gr.isNull(); gr = gr.nextSibling())
604 			{
605 				QDomElement grs = gr.toElement();
606 				if ((grs.tagName() == "vc:firstColor") || (grs.tagName() == "vc:secondColor"))
607 				{
608 					QString stopName = grs.attribute("vc:name");
609 					int tint = 0;
610 					if (grs.attribute("vc:density") == "transparent")
611 						tint = 0;
612 					else
613 						tint = grs.attribute("vc:density").toInt();
614 					if (colorTranslate.contains(stopName))
615 						stopName = colorTranslate[stopName];
616 					else
617 						stopName = "Black";
618 					const ScColor& gradC = m_Doc->PageColors[stopName];
619 					if (grTyp == 6)
620 					{
621 						if (grs.tagName() == "vc:firstColor")
622 							currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), 0.0, 0.5, 1.0, stopName, tint );
623 						else
624 							currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), 1.0, 0.5, 1.0, stopName, tint );
625 					}
626 					else
627 					{
628 						if (grs.tagName() == "vc:firstColor")
629 							currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), 1.0, 0.5, 1.0, stopName, tint );
630 						else
631 							currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), 0.0, 0.5, 1.0, stopName, tint );
632 					}
633 				}
634 			}
635 			if (m_Doc->addGradient(grName, currentGradient))
636 				importedGradients.append(grName);
637 			gradientTranslate.insert(grSelf, grName);
638 			gradientTypeMap.insert(grName, grTyp);
639 		}
640 	}
641 }
642 
parsePreferencesXML(const QDomElement & spNode)643 void VivaPlug::parsePreferencesXML(const QDomElement& spNode)
644 {
645 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
646 	{
647 		for (QDomNode n = spNode.firstChild(); !n.isNull(); n = n.nextSibling() )
648 		{
649 			QDomElement e = n.toElement();
650 			if (e.tagName() == "vd:text")
651 			{
652 				for (QDomNode spo = e.firstChild(); !spo.isNull(); spo = spo.nextSibling())
653 				{
654 					QDomElement eo = spo.toElement();
655 					if (eo.tagName() == "vd:superscriptVerticalOffset")
656 						m_Doc->typographicPrefs().valueSuperScript = eo.text().toInt();
657 					else if (eo.tagName() == "vd:superscriptCharacterHeight")
658 						m_Doc->typographicPrefs().scalingSuperScript = eo.text().toInt();
659 					else if (eo.tagName() == "vd:subscriptVerticalOffset")
660 						m_Doc->typographicPrefs().valueSubScript = eo.text().toInt();
661 					else if (eo.tagName() == "vd:subscriptCharacterHeight")
662 						m_Doc->typographicPrefs().scalingSubScript = eo.text().toInt();
663 					else if (eo.tagName() == "vd:smallCapsCharacterHeight")
664 						m_Doc->typographicPrefs().valueSmallCaps = eo.text().toInt();
665 				}
666 			}
667 		}
668 	}
669 }
670 
parseLayerXML(const QDomElement & spNode)671 void VivaPlug::parseLayerXML(const QDomElement& spNode)
672 {
673 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
674 	{
675 		QString layerName = spNode.attribute("vd:name");
676 		bool printable = true;
677 		bool visible = true;
678 		bool locked = false;
679 		bool flow = false;
680 		int rc = 0;
681 		int gc = 0;
682 		int bc = 0;
683 		for (QDomNode n = spNode.firstChild(); !n.isNull(); n = n.nextSibling() )
684 		{
685 			QDomElement e = n.toElement();
686 			if (e.tagName() == "vd:print")
687 				printable = e.text() == "true";
688 			if (e.tagName() == "vd:hidden")
689 				visible = e.text() == "false";
690 			if (e.tagName() == "vd:locked")
691 				locked = e.text() == "true";
692 			if (e.tagName() == "vd:keepRunaround")
693 				flow = e.text() == "true";
694 			if (e.tagName() == "vd:color")
695 			{
696 				rc = e.attribute("vd:red", "0").toInt();
697 				gc = e.attribute("vd:green", "0").toInt();
698 				bc = e.attribute("vd:blue", "0").toInt();
699 			}
700 		}
701 		int currentLayer = m_Doc->activeLayer();
702 		if (!firstLayer)
703 			currentLayer = m_Doc->addLayer(layerName);
704 		else
705 			m_Doc->changeLayerName(currentLayer, layerName);
706 		m_Doc->setLayerVisible(currentLayer, visible);
707 		m_Doc->setLayerLocked(currentLayer, locked);
708 		m_Doc->setLayerPrintable(currentLayer, printable);
709 		m_Doc->setLayerFlow(currentLayer, flow);
710 		m_Doc->setLayerMarker(currentLayer, QColor(rc, gc, bc));
711 	}
712 	firstLayer = false;
713 }
714 
parseMasterSpreadXML(const QDomElement & spNode)715 void VivaPlug::parseMasterSpreadXML(const QDomElement& spNode)
716 {
717 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
718 	{
719 		bool firstSpread = true;
720 		m_Doc->setMasterPageMode(true);
721 		ScPage *oldCur = m_Doc->currentPage();
722 		for (QDomNode n = spNode.firstChild(); !n.isNull(); n = n.nextSibling() )
723 		{
724 			QString pageNam = spNode.attribute("vd:name");
725 			QDomElement e = n.toElement();
726 			if (e.tagName() == "vd:aliasPage")
727 			{
728 				if (spNode.tagName() == "vd:doubleAliasPage")
729 				{
730 					mspreadTypes.insert(pageNam, 1);
731 					if (firstSpread)
732 						pageNam += "_Left";
733 					else
734 						pageNam += "_Right";
735 				}
736 				else
737 					mspreadTypes.insert(pageNam, 0);
738 				ScPage *addedPage = m_Doc->addMasterPage(mpagecount, pageNam);
739 				m_Doc->setCurrentPage(addedPage);
740 				addedPage->clearMasterPageName();
741 				m_Doc->view()->addPage(mpagecount, true);
742 				baseX = addedPage->xOffset();
743 				baseY = addedPage->yOffset();
744 				mpagecount++;
745 				for (QDomNode spo = e.firstChild(); !spo.isNull(); spo = spo.nextSibling())
746 				{
747 					QDomElement eo = spo.toElement();
748 					if (eo.tagName() == "vo:object")
749 					{
750 						PageItem* ite = parseObjectXML(eo);
751 						if (ite != nullptr)
752 						{
753 							m_Doc->Items->append(ite);
754 							Elements.append(ite);
755 						}
756 					}
757 				}
758 				firstSpread = false;
759 			}
760 		}
761 		m_Doc->setCurrentPage(oldCur);
762 		m_Doc->setMasterPageMode(false);
763 	}
764 }
765 
parseSpreadXML(const QDomElement & spNode)766 void VivaPlug::parseSpreadXML(const QDomElement& spNode)
767 {
768 	for (QDomNode n = spNode.firstChild(); !n.isNull(); n = n.nextSibling() )
769 	{
770 		QDomElement e = n.toElement();
771 		if (e.tagName() == "vd:page")
772 		{
773 			if ((importerFlags & LoadSavePlugin::lfCreateDoc) && (!firstPage))
774 			{
775 				m_Doc->addPage(pagecount);
776 				m_Doc->currentPage()->setSize(papersize);
777 				m_Doc->currentPage()->setInitialHeight(docHeight);
778 				m_Doc->currentPage()->setInitialWidth(docWidth);
779 				m_Doc->currentPage()->setHeight(docHeight);
780 				m_Doc->currentPage()->setWidth(docWidth);
781 				m_Doc->currentPage()->initialMargins.setTop(topMargin);
782 				m_Doc->currentPage()->initialMargins.setBottom(bottomMargin);
783 				m_Doc->currentPage()->initialMargins.setLeft(leftMargin);
784 				m_Doc->currentPage()->initialMargins.setRight(rightMargin);
785 				m_Doc->currentPage()->setMasterPageNameNormal();
786 				m_Doc->view()->addPage(pagecount, true);
787 				pagecount++;
788 			}
789 			baseX = m_Doc->currentPage()->xOffset();
790 			baseY = m_Doc->currentPage()->yOffset();
791 			for (QDomNode sp = e.firstChild(); !sp.isNull(); sp = sp.nextSibling())
792 			{
793 				QDomElement spe = sp.toElement();
794 				if (spe.tagName() == "vd:content")
795 				{
796 					for (QDomNode spo = spe.firstChild(); !spo.isNull(); spo = spo.nextSibling())
797 					{
798 						QDomElement eo = spo.toElement();
799 						if (eo.tagName() == "vo:object")
800 						{
801 							PageItem* ite = parseObjectXML(eo);
802 							if (ite != nullptr)
803 							{
804 								m_Doc->Items->append(ite);
805 								Elements.append(ite);
806 							}
807 						}
808 					}
809 				}
810 				else if (spe.tagName() == "vd:column")
811 				{
812 					if ((importerFlags & LoadSavePlugin::lfCreateDoc) && (firstPage))
813 					{
814 						if (spe.text() == "1")
815 							m_Doc->setPageSetFirstPage(m_Doc->pagePositioning(), 0);
816 						else
817 							m_Doc->setPageSetFirstPage(m_Doc->pagePositioning(), 1);
818 						m_Doc->reformPages(false);
819 						baseX = m_Doc->currentPage()->xOffset();
820 						baseY = m_Doc->currentPage()->yOffset();
821 					}
822 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
823 					{
824 						QString mpage = e.attribute("vd:aliasPageName");
825 						int mType = mspreadTypes[mpage];
826 						if (mType == 1)
827 						{
828 							if (facingPages == 1)
829 							{
830 								if (spe.text() == "1")
831 									mpage += "_Left";
832 								else
833 									mpage += "_Right";
834 							}
835 						}
836 						m_Doc->applyMasterPage(mpage, m_Doc->currentPageNumber());
837 					}
838 				}
839 			}
840 			firstPage = false;
841 		}
842 	}
843 }
844 
parseTextChainsXML(const QDomElement & obNode)845 void VivaPlug::parseTextChainsXML(const QDomElement& obNode)
846 {
847 	if (storyMap.isEmpty())
848 		return;
849 	QDomElement eo = obNode.toElement();
850 	for (QDomNode ob = eo.firstChild(); !ob.isNull(); ob = ob.nextSibling())
851 	{
852 		QDomElement obe = ob.toElement();
853 		if (obe.tagName() == "vd:sequence")
854 		{
855 			QList<PageItem*> GElements;
856 			GElements.clear();
857 			for (QDomNode obg = obe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
858 			{
859 				QDomElement eog = obg.toElement();
860 				if (eog.tagName() == "vd:object")
861 				{
862 					QString id = eog.attribute("vd:id");
863 					if (storyMap.contains(id))
864 						GElements.append(storyMap[id]);
865 				}
866 			}
867 			if (GElements.count() > 1)
868 			{
869 				PageItem *first = GElements[0];
870 				for (int a = 1; a < GElements.count(); a++)
871 				{
872 					PageItem *next = GElements[a];
873 					first->link(next);
874 					next->setColumns(first->columns());
875 					next->setColumnGap(first->columnGap());
876 					first = next;
877 				}
878 			}
879 		}
880 	}
881 }
882 
parseObjectXML(const QDomElement & obNode)883 PageItem* VivaPlug::parseObjectXML(const QDomElement& obNode)
884 {
885 	PageItem *retObj = nullptr;
886 	QDomElement eo = obNode.toElement();
887 	QString id = eo.attribute("vo:id");
888 	for (QDomNode ob = eo.firstChild(); !ob.isNull(); ob = ob.nextSibling())
889 	{
890 		QDomElement obe = ob.toElement();
891 		if (obe.tagName() == "vo:groupObject")
892 		{
893 			QList<PageItem*> GElements;
894 			double ob_xpos = 0;
895 			double ob_ypos = 0;
896 			for (QDomNode obg = obe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
897 			{
898 				QDomElement eog = obg.toElement();
899 				if (eog.tagName() == "vo:object")
900 				{
901 					PageItem *gItem = parseObjectXML(eog);
902 					if (gItem != nullptr)
903 						GElements.append(gItem);
904 				}
905 				else if (eog.tagName() == "vo:transformation")
906 				{
907 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
908 					{
909 						QDomElement eo = spo.toElement();
910 						if (eo.tagName() == "vo:translationX")
911 							ob_xpos = parseUnit(eo.text());
912 						else if (eo.tagName() == "vo:translationY")
913 							ob_ypos = parseUnit(eo.text());
914 					}
915 				}
916 			}
917 			if (GElements.count() > 0)
918 			{
919 				double minx =  std::numeric_limits<double>::max();
920 				double miny =  std::numeric_limits<double>::max();
921 				double maxx = -std::numeric_limits<double>::max();
922 				double maxy = -std::numeric_limits<double>::max();
923 				bool groupClip = true;
924 				for (int ep = 0; ep < GElements.count(); ++ep)
925 				{
926 					PageItem* currItem = GElements.at(ep);
927 					double x1, x2, y1, y2;
928 					currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
929 					minx = qMin(minx, x1);
930 					miny = qMin(miny, y1);
931 					maxx = qMax(maxx, x2);
932 					maxy = qMax(maxy, y2);
933 					if (currItem->hasSoftShadow())
934 						groupClip = false;
935 				}
936 				double gx = minx;
937 				double gy = miny;
938 				double gw = maxx - minx;
939 				double gh = maxy - miny;
940 				int z = m_Doc->itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
941 				if (z >= 0)
942 				{
943 					retObj = m_Doc->Items->at(z);
944 					retObj->ClipEdited = true;
945 					retObj->FrameType = 3;
946 					retObj->setFillEvenOdd(false);
947 					retObj->OldB2 = retObj->width();
948 					retObj->OldH2 = retObj->height();
949 					retObj->updateClip();
950 					m_Doc->groupObjectsToItem(retObj, GElements);
951 					retObj->setGroupClipping(groupClip);
952 					retObj->moveBy(ob_xpos, ob_ypos, true);
953 					m_Doc->adjustItemSize(retObj);
954 					retObj->OwnPage = m_Doc->OnPage(retObj);
955 					m_Doc->GroupOnPage(retObj);
956 					m_Doc->Items->removeLast();
957 				}
958 			}
959 		}
960 		else if (obe.tagName() == "vo:graphicObject")
961 			retObj = parseObjectDetailsXML(obe, 0);
962 		else if (obe.tagName() == "vo:pictureObject")
963 			retObj = parseObjectDetailsXML(obe, 1);
964 		else if (obe.tagName() == "vo:textObject")
965 		{
966 			retObj = parseObjectDetailsXML(obe, 2);
967 			storyMap.insert(id, retObj);
968 		}
969 	}
970 	return retObj;
971 }
972 
parseObjectDetailsXML(const QDomElement & obNode,int baseType)973 PageItem* VivaPlug::parseObjectDetailsXML(const QDomElement& obNode, int baseType)
974 {
975 	PageItem *retObj = nullptr;
976 	QDomElement eo = obNode.toElement();
977 	double ob_width = 0;
978 	double ob_height = 0;
979 	double ob_xpos = 0;
980 	double ob_ypos = 0;
981 	double ob_rotation = 0;
982 	QString fillColor = CommonStrings::None;
983 	QString strokeColor = CommonStrings::None;
984 	QString fillGradient = "";
985 	int fillGradientTyp = 6;
986 	int fillTint = 100;
987 	int strokeTint = 100;
988 	double lineWidth = 0;
989 	double fillOpacity = 0.0;
990 	double strokeOpacity = 0.0;
991 	double imageOpacity = 0.0;
992 	double gradientAngle = 0.0;
993 	double imageXoffs = 0;
994 	double imageYoffs = 0;
995 	double imageScaleX = 1.0;
996 //	double imageScaleY = 1.0;
997 	double cornerRadius = 0.0;
998 	int ob_type = 0;
999 	bool printable = false;
1000 	bool locked = false;
1001 	bool resizable = false;
1002 	FPointArray Path;
1003 	Path.resize(0);
1004 	QString imageFile = "";
1005 	QByteArray imageData;
1006 	imageData.resize(0);
1007 	QVector<double> DashValues;
1008 	DashValues.clear();
1009 	int LineStyle = 0;
1010 	int ArrowLeft = 1;
1011 	int ArrowRight = 1;
1012 	double textMarginLeft = 0.0;
1013 	double textMarginRight = 0.0;
1014 	double textMarginTop = 0.0;
1015 	double textMarginBottom = 0.0;
1016 	double textColumnGap = 0.0;
1017 	int textColumnCount = 1;
1018 	bool hasShadow = false;
1019 	double shadowX = 0.0;
1020 	double shadowY = 0.0;
1021 	double shadowBlur = 0.0;
1022 	double shadowOpacity = 0.0;
1023 	int shadowTint = 100;
1024 	bool shadowErase = false;
1025 	bool shadowObjTrans = false;
1026 	QString shadowColor = "Black";
1027 	StoryText itemText;
1028 	itemText.clear();
1029 	PageItem::TextFlowMode textFlow = PageItem::TextFlowDisabled;
1030 	for (QDomNode ob = eo.firstChild(); !ob.isNull(); ob = ob.nextSibling())
1031 	{
1032 		QDomElement obe = ob.toElement();
1033 		if ((obe.tagName() == "vo:rectangle") || (obe.tagName() == "vo:oval") || (obe.tagName() == "vo:polygon") || (obe.tagName() == "vo:line") || (obe.tagName() == "vo:polyline"))
1034 		{
1035 			if (obe.tagName() == "vo:rectangle")
1036 				ob_type = 0;
1037 			if (obe.tagName() == "vo:oval")
1038 				ob_type = 1;
1039 			if (obe.tagName() == "vo:polygon")
1040 				ob_type = 2;
1041 			if (obe.tagName() == "vo:line")
1042 				ob_type = 3;
1043 			if (obe.tagName() == "vo:polyline")
1044 				ob_type = 4;
1045 			for (QDomNode obg = obe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
1046 			{
1047 				QDomElement eog = obg.toElement();
1048 				if (eog.tagName() == "vo:size")
1049 				{
1050 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1051 					{
1052 						QDomElement eo = spo.toElement();
1053 						if (eo.tagName() == "vo:width")
1054 							ob_width = parseUnit(eo.text());
1055 						else if (eo.tagName() == "vo:height")
1056 							ob_height = parseUnit(eo.text());
1057 					}
1058 				}
1059 				else if (eog.tagName() == "vo:transformation")
1060 				{
1061 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1062 					{
1063 						QDomElement eo = spo.toElement();
1064 						if (eo.tagName() == "vo:translationX")
1065 							ob_xpos = parseUnit(eo.text());
1066 						else if (eo.tagName() == "vo:translationY")
1067 							ob_ypos = parseUnit(eo.text());
1068 						else if (eo.tagName() == "vo:rotation")
1069 							ob_rotation = eo.text().toDouble();
1070 					}
1071 				}
1072 				else if (eog.tagName() == "vo:design")
1073 				{
1074 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1075 					{
1076 						QDomElement eo = spo.toElement();
1077 						if (eo.tagName() == "vo:lineColor")
1078 							strokeColor = colorTranslate[eo.text()];
1079 						else if (eo.tagName() == "vo:fillColor")
1080 						{
1081 							if (colorTranslate.contains(eo.text()))
1082 								fillColor = colorTranslate[eo.text()];
1083 							else if (gradientTranslate.contains(eo.text()))
1084 							{
1085 								fillGradient = gradientTranslate[eo.text()];
1086 								fillGradientTyp = gradientTypeMap[fillGradient];
1087 							}
1088 						}
1089 						else if (eo.tagName() == "vo:lineDensity")
1090 						{
1091 							if (eo.text() == "transparent")
1092 								strokeTint = 0;
1093 							else if (eo.text() == "opaque")
1094 								strokeTint = 100;
1095 							else
1096 								strokeTint = eo.text().toInt();
1097 						}
1098 						else if (eo.tagName() == "vo:fillDensity")
1099 						{
1100 							if (eo.text() == "transparent")
1101 								fillTint = 0;
1102 							else if (eo.text() == "opaque")
1103 								fillTint = 100;
1104 							else
1105 								fillTint = eo.text().toInt();
1106 						}
1107 						else if (eo.tagName() == "vo:lineWidth")
1108 							lineWidth = parseUnit(eo.text());
1109 						else if (eo.tagName() == "vo:lineStyle")
1110 						{
1111 							QString Lstyle = eo.text();
1112 							if (Lstyle != "Solid")
1113 							{
1114 								if (Lstyle == "2")
1115 									DashValues << 3 << 2;
1116 								else if (Lstyle == "3")
1117 									LineStyle = 15;
1118 								else if (Lstyle == "4")
1119 									DashValues << 5 << 2.2 << 1 << 2.2;
1120 								else if (Lstyle == "5")
1121 									LineStyle = 6;
1122 								else if (Lstyle == "6")
1123 									DashValues << 2 << 3.1;
1124 								else if ((Lstyle == "7") || (Lstyle == "10"))
1125 									LineStyle = 21;
1126 								else if (Lstyle == "8")
1127 									DashValues << 4 << 3.2 << 0.2 << 3.2;
1128 								else if (Lstyle == "9")
1129 									DashValues << 0.2 << 2;
1130 							}
1131 						}
1132 						else if (eo.tagName() == "vo:startCap")
1133 						{
1134 							ArrowLeft = eo.text().toInt();
1135 							if (ArrowLeft == 2)
1136 								ArrowLeft = 3;
1137 							else if (ArrowLeft == 3)
1138 								ArrowLeft = 18;
1139 							else if (ArrowLeft == 4)
1140 								ArrowLeft = 6;
1141 						}
1142 						else if (eo.tagName() == "vo:endCap")
1143 						{
1144 							ArrowRight = eo.text().toInt();
1145 							if (ArrowRight == 2)
1146 								ArrowRight = 3;
1147 							else if (ArrowRight == 3)
1148 								ArrowRight = 18;
1149 							else if (ArrowRight == 4)
1150 								ArrowRight = 6;
1151 						}
1152 						else if (eo.tagName() == "vo:blendAngle")
1153 							gradientAngle = eo.text().toDouble();
1154 						else if (eo.tagName() == "vo:fillOpacity")
1155 						{
1156 							if (eo.text() == "transparent")
1157 								fillOpacity = 1;
1158 							else if (eo.text() == "opaque")
1159 								fillOpacity = 0;
1160 							else
1161 								fillOpacity = 1.0 - (eo.text().toDouble() / 100.0);
1162 						}
1163 						else if (eo.tagName() == "vo:lineOpacity")
1164 						{
1165 							if (eo.text() == "transparent")
1166 								strokeOpacity = 1;
1167 							else if (eo.text() == "opaque")
1168 								strokeOpacity = 0;
1169 							else
1170 								strokeOpacity = 1.0 - (eo.text().toDouble() / 100.0);
1171 						}
1172 						else if (eo.tagName() == "vo:baseOpacity")
1173 						{
1174 							double opa = 0.0;
1175 							if (eo.text() == "transparent")
1176 								opa = 1;
1177 							else if (eo.text() == "opaque")
1178 								opa = 0;
1179 							else
1180 								opa = 1.0 - (eo.text().toDouble() / 100.0);
1181 							fillOpacity = 1.0 - ((1.0 - fillOpacity) * (1.0 - opa));
1182 							strokeOpacity = 1.0 - ((1.0 - strokeOpacity) * (1.0 - opa));
1183 						}
1184 						else if (eo.tagName() == "vo:cornerRadius")
1185 							cornerRadius = parseUnit(eo.text());
1186 					}
1187 				}
1188 				else if (eog.tagName() == "vo:points")
1189 				{
1190 					Path.resize(0);
1191 					bool hasBefore = false;
1192 					bool hasAfter = false;
1193 					triplePoint triPoint;
1194 					QList<triplePoint> tPoints;
1195 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1196 					{
1197 						QDomElement eo = spo.toElement();
1198 						if (eo.tagName() == "vo:point")
1199 						{
1200 							FPoint pp = FPoint(parseUnit(eo.attribute("vo:x", "0")), parseUnit(eo.attribute("vo:y", "0")));
1201 							if (eo.hasAttribute("vo:control"))
1202 							{
1203 								if ((eo.attribute("vo:control") == "constraint-before") || (eo.attribute("vo:control") == "before"))
1204 									hasBefore = true;
1205 								else if ((eo.attribute("vo:control") == "constraint-after") || (eo.attribute("vo:control") == "after"))
1206 									hasAfter = true;
1207 							}
1208 							if ((hasBefore) && ((eo.attribute("vo:control") == "constraint-before") || (eo.attribute("vo:control") == "before")))
1209 								triPoint.beforePolyPoint = pp;
1210 							else if (hasAfter && hasBefore)
1211 							{
1212 								triPoint.afterPolyPoint = pp;
1213 								tPoints.append(triPoint);
1214 								hasBefore = false;
1215 								hasAfter = false;
1216 							}
1217 							else if (hasBefore)
1218 								triPoint.PolyPoint = pp;
1219 							else
1220 							{
1221 								triPoint.beforePolyPoint = pp;
1222 								triPoint.PolyPoint = pp;
1223 								triPoint.afterPolyPoint = pp;
1224 								tPoints.append(triPoint);
1225 								hasBefore = false;
1226 								hasAfter = false;
1227 							}
1228 						}
1229 					}
1230 					if (tPoints.count() > 0)
1231 					{
1232 						if (ob_type == 2)
1233 						{
1234 							Path.addPoint(tPoints[0].PolyPoint);
1235 							Path.addPoint(tPoints[0].afterPolyPoint);
1236 							for (int ppx = 1; ppx < tPoints.count(); ppx++)
1237 							{
1238 								Path.addPoint(tPoints[ppx].PolyPoint);
1239 								Path.addPoint(tPoints[ppx].beforePolyPoint);
1240 								Path.addPoint(tPoints[ppx].PolyPoint);
1241 								Path.addPoint(tPoints[ppx].afterPolyPoint);
1242 							}
1243 							Path.addPoint(tPoints[0].PolyPoint);
1244 							Path.addPoint(tPoints[0].beforePolyPoint);
1245 						}
1246 						else if (ob_type == 3)
1247 						{
1248 							Path.addPoint(tPoints[0].PolyPoint);
1249 							Path.addPoint(tPoints[0].PolyPoint);
1250 							Path.addPoint(tPoints[1].PolyPoint);
1251 							Path.addPoint(tPoints[1].PolyPoint);
1252 						}
1253 						else if (ob_type == 4)
1254 						{
1255 							Path.addPoint(tPoints[0].PolyPoint);
1256 							Path.addPoint(tPoints[0].afterPolyPoint);
1257 							for (int ppx = 1; ppx < tPoints.count()-1; ppx++)
1258 							{
1259 								Path.addPoint(tPoints[ppx].PolyPoint);
1260 								Path.addPoint(tPoints[ppx].beforePolyPoint);
1261 								Path.addPoint(tPoints[ppx].PolyPoint);
1262 								Path.addPoint(tPoints[ppx].afterPolyPoint);
1263 							}
1264 							Path.addPoint(tPoints[tPoints.count()-1].PolyPoint);
1265 							Path.addPoint(tPoints[tPoints.count()-1].beforePolyPoint);
1266 						}
1267 					}
1268 				}
1269 				else if (eog.tagName() == "vo:shadow")
1270 				{
1271 					hasShadow = true;
1272 					double shadowAngle = 0;
1273 					double shadowOffset = 0;
1274 					for (QDomElement spo = eog.firstChildElement(); !spo.isNull(); spo = spo.nextSiblingElement())
1275 					{
1276 						if (spo.tagName() == "uni:color")
1277 							shadowColor = colorTranslate[spo.text()];
1278 						else if (spo.tagName() == "uni:opacity")
1279 						{
1280 							if (spo.text() == "transparent")
1281 								shadowOpacity = 1;
1282 							else if (spo.text() == "opaque")
1283 								shadowOpacity = 0;
1284 							else
1285 								shadowOpacity = 1.0 - (spo.text().toDouble() / 100.0);
1286 						}
1287 						else if (spo.tagName() == "uni:density")
1288 						{
1289 							if (spo.text() == "transparent")
1290 								shadowTint = 0;
1291 							else if (spo.text() == "opaque")
1292 								shadowTint = 100;
1293 							else
1294 								shadowTint = spo.text().toInt();
1295 						}
1296 						else if (spo.tagName() == "uni:angle")
1297 							shadowAngle = spo.text().toDouble();
1298 						else if (spo.tagName() == "uni:offset")
1299 							shadowOffset = parseUnit(spo.text());
1300 						else if (spo.tagName() == "uni:softValue")
1301 							shadowBlur = parseUnit(spo.text());
1302 						else if (spo.tagName() == "uni:coverShadow")
1303 							shadowErase = (spo.text() == "true");
1304 						else if (spo.tagName() == "uni:applyElementOpacity")
1305 							shadowObjTrans = (spo.text() == "true");
1306 					}
1307 					QLineF oLine = QLineF(0, 0, shadowOffset, 0);
1308 					oLine.setAngle(shadowAngle - 180.0);
1309 					shadowX = oLine.p2().x();
1310 					shadowY = oLine.p2().y();
1311 				}
1312 			}
1313 		}
1314 		else if (obe.tagName() == "vo:properties")
1315 		{
1316 			for (QDomNode obg = obe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
1317 			{
1318 				QDomElement eog = obg.toElement();
1319 				if (eog.tagName() == "vo:printable")
1320 					printable = eog.text() == "true";
1321 				else if (eog.tagName() == "vo:protected")
1322 					locked = eog.text() == "true";
1323 				else if (eog.tagName() == "vo:fixed")
1324 					resizable = eog.text() == "true";
1325 			}
1326 		}
1327 		else if (obe.tagName() == "vo:runaround")
1328 		{
1329 			if ((obe.attribute("vo:mode") == "all") || (obe.attribute("vo:mode") == "left") || (obe.attribute("vo:mode") == "right"))
1330 			{
1331 				textFlow = PageItem::TextFlowUsesFrameShape;
1332 				for (QDomNode obg = obe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
1333 				{
1334 					QDomElement eog = obg.toElement();
1335 					if (eog.tagName() == "vo:shape")
1336 					{
1337 						textFlow = PageItem::TextFlowUsesFrameShape;
1338 						break;
1339 					}
1340 					if (eog.tagName() == "vo:block")
1341 					{
1342 						textFlow = PageItem::TextFlowUsesBoundingBox;
1343 						break;
1344 					}
1345 				}
1346 			}
1347 		}
1348 		else if (obe.tagName() == "vo:content")
1349 		{
1350 			for (QDomNode obg = obe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
1351 			{
1352 				QDomElement eog = obg.toElement();
1353 				if (eog.tagName() == "vo:filePath")
1354 				{
1355 					QString fileP = eog.text();
1356 					QFileInfo fp(fileP);
1357 					if (fp.exists())
1358 						imageFile = fileP;
1359 					else
1360 					{
1361 						QString  fileName = fp.fileName();
1362 						QFileInfo fi2(fileName);
1363 						if (fi2.exists())
1364 							imageFile = fileName;
1365 						else
1366 							imageFile = fileP;
1367 					}
1368 				}
1369 				else if (eog.tagName() == "vo:fillOpacity")
1370 				{
1371 					if (eog.text() == "transparent")
1372 						imageOpacity = 1;
1373 					else if (eog.text() == "opaque")
1374 						imageOpacity = 0;
1375 					else
1376 						imageOpacity = 1.0 - (eog.text().toDouble() / 100.0);
1377 				}
1378 				else if (eog.tagName() == "vo:transformation")
1379 				{
1380 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1381 					{
1382 						QDomElement eo = spo.toElement();
1383 						if (eo.tagName() == "vo:translationX")
1384 							imageXoffs = parseUnit(eo.text());
1385 						else if (eo.tagName() == "vo:translationY")
1386 							imageYoffs = parseUnit(eo.text());
1387 						else if (eo.tagName() == "vo:scaleHorizontal")
1388 							imageScaleX = eo.text().toDouble() / 100.0;
1389 					//	else if (eo.tagName() == "vo:scaleVertical")
1390 					//		imageScaleY = eo.text().toDouble() / 100.0;
1391 					}
1392 				}
1393 				else if (eog.tagName() == "vo:preview")
1394 					imageData = QByteArray::fromBase64(eog.text().toLatin1());
1395 				else if (eog.tagName() == "vo:areaStructure")
1396 				{
1397 					for (QDomNode spo = eog.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1398 					{
1399 						QDomElement eo = spo.toElement();
1400 						if (eo.tagName() == "uni:indents")
1401 						{
1402 							for (QDomNode stx = eo.firstChild(); !stx.isNull(); stx = stx.nextSibling())
1403 							{
1404 								QDomElement stxe = stx.toElement();
1405 								if (stxe.tagName() == "uni:left")
1406 									textMarginLeft = parseUnit(stxe.text());
1407 								else if (stxe.tagName() == "uni:right")
1408 									textMarginRight = parseUnit(stxe.text());
1409 								else if (stxe.tagName() == "uni:top")
1410 									textMarginTop = parseUnit(stxe.text());
1411 								else if (stxe.tagName() == "uni:bottom")
1412 									textMarginBottom = parseUnit(stxe.text());
1413 							}
1414 						}
1415 						else if (eo.tagName() == "uni:columns")
1416 						{
1417 							for (QDomNode stx = eo.firstChild(); !stx.isNull(); stx = stx.nextSibling())
1418 							{
1419 								QDomElement stxe = stx.toElement();
1420 								if (stxe.tagName() == "uni:distance")
1421 									textColumnGap = parseUnit(stxe.text());
1422 								else if (stxe.tagName() == "uni:count")
1423 									textColumnCount = stxe.text().toInt();
1424 							}
1425 						}
1426 					}
1427 				}
1428 				else if (eog.tagName() == "vtr:vivaText")
1429 				{
1430 					itemText.setDoc(m_Doc);
1431 					parseTextXML(eog, itemText, textColumnCount, textColumnGap);
1432 				}
1433 			}
1434 		}
1435 	}
1436 	int z = -1;
1437 	if (baseType == 0)
1438 	{
1439 		if (ob_type == 0)
1440 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1441 		else if (ob_type == 1)
1442 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1443 		else if (ob_type == 2)
1444 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1445 		else if (ob_type == 3)
1446 			z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1447 		else if (ob_type == 4)
1448 			z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1449 	}
1450 	else if (baseType == 1)
1451 	{
1452 		if (ob_type == 0)
1453 			z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1454 		else if (ob_type == 1)
1455 			z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Ellipse, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1456 		else if (ob_type == 2)
1457 			z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1458 	}
1459 	else if (baseType == 2)
1460 	{
1461 		if (ob_type == 0)
1462 			z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1463 		else if (ob_type == 1)
1464 			z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Ellipse, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1465 		else if (ob_type == 2)
1466 			z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, baseX, baseY, ob_width, ob_height, lineWidth, fillColor, strokeColor);
1467 	}
1468 	if (z >= 0)
1469 	{
1470 		PageItem* item = m_Doc->Items->at(z);
1471 		item->setTextFlowMode(textFlow);
1472 		if (((ob_type == 2) || (ob_type == 3) || (ob_type == 4)) && (Path.count() > 0))
1473 		{
1474 			item->PoLine = Path.copy();
1475 			FPoint wh = getMaxClipF(&item->PoLine);
1476 			item->setWidthHeight(wh.x(),wh.y());
1477 			m_Doc->adjustItemSize(item, true);
1478 		}
1479 		item->ClipEdited = true;
1480 		if ((cornerRadius != 0) && (item->frameType() == PageItem::Rectangle))
1481 		{
1482 			item->setCornerRadius(cornerRadius);
1483 			item->SetFrameRound();
1484 		}
1485 		else
1486 			item->FrameType = 3;
1487 		if (fillTint == 0)
1488 		{
1489 			item->setFillColor(CommonStrings::None);
1490 			item->setFillShade(100);
1491 		}
1492 		else
1493 		{
1494 			item->setFillColor(fillColor);
1495 			item->setFillShade(fillTint);
1496 		}
1497 		if (strokeTint == 0)
1498 		{
1499 			item->setLineColor(CommonStrings::None);
1500 			item->setLineShade(100);
1501 		}
1502 		else
1503 		{
1504 			item->setLineColor(strokeColor);
1505 			item->setLineShade(strokeTint);
1506 		}
1507 		if (baseType == 1)
1508 			item->setFillTransparency(imageOpacity);
1509 		else
1510 			item->setFillTransparency(fillOpacity);
1511 		item->setLineTransparency(strokeOpacity);
1512 		if (!fillGradient.isEmpty())
1513 		{
1514 			QLineF gradientVectorE;
1515 			gradientVectorE.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
1516 			gradientVectorE.setAngle(gradientAngle);
1517 			gradientVectorE.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
1518 			QPointF gradEnd = intersectBoundingRect(item, gradientVectorE);
1519 			QLineF gradientVectorS;
1520 			gradientVectorS.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
1521 			gradientVectorS.setAngle(gradientAngle + 180);
1522 			gradientVectorS.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
1523 			QPointF gradStart = intersectBoundingRect(item, gradientVectorS);
1524 			item->fill_gradient = m_Doc->docGradients[fillGradient];
1525 			if (fillGradientTyp == 6)
1526 			{
1527 				item->setGradientVector(gradStart.x(), gradStart.y(), gradEnd.x(), gradEnd.y(), gradStart.x(), gradStart.y(), 1, 0);
1528 				item->setGradient(fillGradient);
1529 				item->setGradientType(fillGradientTyp);
1530 			}
1531 			else if (fillGradientTyp == 7)
1532 			{
1533 				QList<VColorStop*> colorStops = item->fill_gradient.colorStops();
1534 				QString gradColor2Str = colorStops[0]->name;
1535 				QColor gradColor2 = colorStops[0]->color;
1536 				QString gradColor1Str = colorStops[1]->name;
1537 				QColor gradColor1 = colorStops[1]->color;
1538 				item->meshGradientPatches.clear();
1539 				FPoint center = FPoint(item->width() / 2.0, item->height() / 2.0);
1540 				MeshPoint cP;
1541 				cP.resetTo(center);
1542 				cP.transparency = 1.0;
1543 				cP.shade = 100;
1544 				cP.colorName = gradColor2Str;
1545 				cP.color = gradColor2;
1546 				for (int poi = 0; poi < item->PoLine.size()-3; poi += 4)
1547 				{
1548 					meshGradientPatch patch;
1549 					patch.BL = cP;
1550 					patch.BR = cP;
1551 					if (item->PoLine.isMarker(poi))
1552 						continue;
1553 					MeshPoint tL;
1554 					tL.resetTo(item->PoLine.point(poi));
1555 					tL.controlRight = item->PoLine.point(poi + 1);
1556 					tL.transparency = 1.0;
1557 					tL.shade = 100;
1558 					tL.colorName = gradColor1Str;
1559 					tL.color = gradColor1;
1560 					MeshPoint tR;
1561 					tR.resetTo(item->PoLine.point(poi + 2));
1562 					tR.controlLeft = item->PoLine.point(poi + 3);
1563 					tR.transparency = 1.0;
1564 					tR.shade = 100;
1565 					tR.colorName = gradColor1Str;
1566 					tR.color = gradColor1;
1567 					patch.TL = tL;
1568 					patch.TR = tR;
1569 					item->meshGradientPatches.append(patch);
1570 				}
1571 				item->GrType = Gradient_PatchMesh;
1572 			}
1573 			else
1574 			{
1575 				item->GrControl1 = FPoint(0, 0);
1576 				item->GrControl2 = FPoint(item->width(), 0);
1577 				item->GrControl3 = FPoint(item->width(), item->height());
1578 				item->GrControl4 = FPoint(0, item->height());
1579 				if (gradientAngle != 0)
1580 				{
1581 					QLineF gradientVector = QLineF(item->width() / 2.0, item->height() / 2.0, 0, 0);
1582 					gradientVector.setLength(gradientVector.length() + 1);
1583 					gradientVector.setAngle(gradientVector.angle() + gradientAngle);
1584 					QPointF g1 = intersectBoundingRect(item, gradientVector);
1585 					item->GrControl1 = FPoint(g1.x(), g1.y());
1586 					gradientVector = QLineF(item->width() / 2.0, item->height() / 2.0, item->width(), 0);
1587 					gradientVector.setLength(gradientVector.length() + 1);
1588 					gradientVector.setAngle(gradientVector.angle() + gradientAngle);
1589 					g1 = intersectBoundingRect(item, gradientVector);
1590 					item->GrControl2 = FPoint(g1.x(), g1.y());
1591 					gradientVector = QLineF(item->width() / 2.0, item->height() / 2.0, item->width(), item->height());
1592 					gradientVector.setLength(gradientVector.length() + 1);
1593 					gradientVector.setAngle(gradientVector.angle() + gradientAngle);
1594 					g1 = intersectBoundingRect(item, gradientVector);
1595 					item->GrControl3 = FPoint(g1.x(), g1.y());
1596 					gradientVector = QLineF(item->width() / 2.0, item->height() / 2.0, 0, item->height());
1597 					gradientVector.setLength(gradientVector.length() + 1);
1598 					gradientVector.setAngle(gradientVector.angle() + gradientAngle);
1599 					g1 = intersectBoundingRect(item, gradientVector);
1600 					item->GrControl4 = FPoint(g1.x(), g1.y());
1601 				}
1602 				item->GrControl5 = FPoint(item->width() / 2.0, item->height() / 2.0);
1603 				item->setGradient(fillGradient);
1604 				item->setGradientType(fillGradientTyp);
1605 			}
1606 		}
1607 		item->setDashOffset(0);
1608 		if (!DashValues.isEmpty())
1609 		{
1610 			QVector<double> pattern(DashValues.count());
1611 			for (int i = 0; i < DashValues.count(); ++i)
1612 			{
1613 				pattern[i] = DashValues[i] * lineWidth;
1614 			}
1615 			item->setDashes(pattern);
1616 		}
1617 		else
1618 			item->setLineStyle(Qt::PenStyle(LineStyle));
1619 		if (ArrowLeft > 1)
1620 			item->setStartArrowIndex(ArrowLeft);
1621 		if (ArrowRight > 1)
1622 			item->setEndArrowIndex(ArrowRight);
1623 		item->setRotation(-ob_rotation, true);
1624 		item->moveBy(ob_xpos, ob_ypos, true);
1625 		item->setFillEvenOdd(false);
1626 		item->OldB2 = item->width();
1627 		item->OldH2 = item->height();
1628 		item->updateClip();
1629 		item->OwnPage = m_Doc->OnPage(item);
1630 		item->ContourLine = item->PoLine.copy();
1631 		if (hasShadow)
1632 		{
1633 			item->setHasSoftShadow(true);
1634 			item->setSoftShadowColor(shadowColor);
1635 			item->setSoftShadowXOffset(shadowX);
1636 			item->setSoftShadowYOffset(shadowY);
1637 			item->setSoftShadowBlurRadius(shadowBlur);
1638 			item->setSoftShadowShade(shadowTint);
1639 			item->setSoftShadowOpacity(shadowOpacity);
1640 			item->setSoftShadowBlendMode(0);
1641 			item->setSoftShadowErasedByObject(shadowErase);
1642 			item->setSoftShadowHasObjectTransparency(shadowObjTrans);
1643 		}
1644 		if (baseType == 1)
1645 		{
1646 			item->AspectRatio = true;
1647 			item->ScaleType   = false;
1648 			bool erf = m_Doc->loadPict(imageFile, item);
1649 			if (!erf)
1650 			{
1651 				if (!imageData.isEmpty())
1652 				{
1653 					QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_viva_XXXXXX.png");
1654 					tempFile->setAutoRemove(false);
1655 					if (tempFile->open())
1656 					{
1657 						QString fileName = getLongPathName(tempFile->fileName());
1658 						if (!fileName.isEmpty())
1659 						{
1660 							tempFile->write(imageData);
1661 							tempFile->close();
1662 							item->isInlineImage = true;
1663 							item->isTempFile = true;
1664 							item->AspectRatio = true;
1665 							item->ScaleType   = false;
1666 							m_Doc->loadPict(fileName, item);
1667 						}
1668 					}
1669 					delete tempFile;
1670 				}
1671 			}
1672 			item->setImageXYScale(imageScaleX / item->pixm.imgInfo.xres * 72, imageScaleX / item->pixm.imgInfo.xres * 72);
1673 			item->setImageXYOffset(imageXoffs / item->imageXScale(), imageYoffs / item->imageYScale());
1674 		}
1675 		else if (baseType == 2)
1676 		{
1677 			item->setTextToFrameDist(textMarginLeft, textMarginRight, textMarginTop, textMarginBottom);
1678 			item->setColumns(textColumnCount);
1679 			item->setColumnGap(textColumnGap);
1680 			if (itemText.length() > 0)
1681 				item->itemText.append(itemText);
1682 			item->itemText.trim();
1683 		}
1684 		item->setLocked(locked);
1685 		item->setSizeLocked(resizable);
1686 		item->setPrintEnabled(printable);
1687 		retObj = m_Doc->Items->takeAt(z);
1688 	}
1689 	return retObj;
1690 }
1691 
parseTextXML(const QDomElement & obNode,StoryText & itemText,int & textColumnCount,double & textColumnGap)1692 void VivaPlug::parseTextXML(const QDomElement& obNode, StoryText &itemText, int &textColumnCount, double &textColumnGap)
1693 {
1694 	QString pStyle = CommonStrings::DefaultParagraphStyle;
1695 	ParagraphStyle newStyle;
1696 	newStyle.setDefaultStyle(false);
1697 	newStyle.setParent(pStyle);
1698 	ParagraphStyle ttx = m_Doc->paragraphStyle(pStyle);
1699 	CharStyle nstyle = ttx.charStyle();
1700 	newStyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
1701 	newStyle.setLineSpacing(nstyle.fontSize() / 10.0);
1702 	itemText.setDefaultStyle(newStyle);
1703 	int posC = 0;
1704 	for (QDomNode spo = obNode.firstChild(); !spo.isNull(); spo = spo.nextSibling())
1705 	{
1706 		QDomElement eo = spo.toElement();
1707 		if (eo.tagName() == "vs:stylesheets")
1708 			parseStylesheetsXML(eo);
1709 		else if (eo.tagName() == "vs:attribute-sets")
1710 			parseAttributeSetsXML(eo);
1711 		else if (eo.tagName() == "vt:story")
1712 		{
1713 			if (eo.hasAttribute("vt:story-attribute-set"))
1714 			{
1715 				applyParagraphAttrs(newStyle, AttributeSets[eo.attribute("vt:story-attribute-set")]);
1716 				applyCharacterAttrs(newStyle.charStyle(), newStyle, AttributeSets[eo.attribute("vt:story-attribute-set")]);
1717 			}
1718 			for (QDomNode stx = eo.firstChild(); !stx.isNull(); stx = stx.nextSibling())
1719 			{
1720 				QDomElement stxe = stx.toElement();
1721 				if (stxe.tagName() == "vt:chapter")
1722 				{
1723 					for (QDomNode st = stxe.firstChild(); !st.isNull(); st = st.nextSibling())
1724 					{
1725 						QDomElement ste = st.toElement();
1726 						if (ste.tagName() == "vt:layout")
1727 						{
1728 							if (ste.hasAttribute("vt:layout-attribute-set"))
1729 							{
1730 								AttributeSet attrs = AttributeSets[ste.attribute("vt:layout-attribute-set")];
1731 								if (attrs.columnCount.valid)
1732 									textColumnCount = attrs.columnCount.value.toInt();
1733 								if (attrs.columnGutter.valid)
1734 									textColumnGap = attrs.columnGutter.value.toDouble();
1735 							}
1736 							for (QDomNode stc = ste.firstChild(); !stc.isNull(); stc = stc.nextSibling())
1737 							{
1738 								QDomElement stce = stc.toElement();
1739 								if (stce.tagName() == "vt:p")
1740 								{
1741 									ParagraphStyle tmpStyle = newStyle;
1742 									if (stce.hasAttribute("vt:paragraph-attribute-set"))
1743 									{
1744 										if (AttributeSets.contains(stce.attribute("vt:paragraph-attribute-set")))
1745 											applyParagraphAttrs(tmpStyle, AttributeSets[stce.attribute("vt:paragraph-attribute-set")]);
1746 										else if (m_Doc->styleExists(stce.attribute("vt:paragraph-attribute-set")))
1747 											tmpStyle = m_Doc->paragraphStyle(stce.attribute("vt:paragraph-attribute-set"));
1748 									}
1749 									for (QDomNode stces = stce.firstChild(); !stces.isNull(); stces = stces.nextSibling())
1750 									{
1751 										QDomElement stcet = stces.toElement();
1752 										if (stcet.tagName() == "vt:span")
1753 										{
1754 											CharStyle tmpCStyle = tmpStyle.charStyle();
1755 											if (stcet.hasAttribute("vt:character-attribute-set"))
1756 												applyCharacterAttrs(tmpCStyle, tmpStyle, AttributeSets[stcet.attribute("vt:character-attribute-set")]);
1757 											for (QDomNode stcesp = stcet.firstChild(); !stcesp.isNull(); stcesp = stcesp.nextSibling())
1758 											{
1759 												QDomElement stcespt = stcesp.toElement();
1760 												int count = stcespt.text().length();
1761 												if (stcespt.tagName() == "vt:plain-text")
1762 													itemText.insertChars(posC, stcespt.text());
1763 												else if (stcespt.tagName() == "vt:lf")
1764 												{
1765 													count = 1;
1766 													itemText.insertChars(posC, SpecialChars::LINEBREAK);
1767 												}
1768 												else if (stcespt.tagName() == "vt:soft-hyphen")
1769 												{
1770 													count = 1;
1771 													itemText.insertChars(posC, SpecialChars::SHYPHEN);
1772 												}
1773 												else if (stcespt.tagName() == "vt:space")
1774 												{
1775 													if (stcespt.attribute("vt:br") == "false")
1776 													{
1777 														count = 1;
1778 														itemText.insertChars(posC, SpecialChars::NBSPACE);
1779 													}
1780 												}
1781 												else if (stcespt.tagName() == "vt:variable")
1782 												{
1783 													if (stcespt.attribute("vt:type") == "Viva Technology/Page Number")
1784 													{
1785 														count = 1;
1786 														itemText.insertChars(posC, SpecialChars::PAGENUMBER);
1787 													}
1788 													else if (stcespt.attribute("vt:type") == "Viva Technology/Number of Pages")
1789 													{
1790 														count = 1;
1791 														itemText.insertChars(posC, SpecialChars::PAGECOUNT);
1792 													}
1793 												/*	else if (stcespt.attribute("vt:type") == "Viva Technology/TextEngine/Date")
1794 													{
1795 														QDomNode anc = stcespt.firstChild();
1796 														QDomElement anco = anc.toElement();
1797 														if (anco.tagName() == "uni:data")
1798 														{
1799 															QByteArray data;
1800 															if (anco.hasAttribute("uni:encoder") && (anco.attribute("uni:encoder") == "base64"))
1801 																data = QByteArray::fromBase64(anco.text().toLatin1());
1802 															else
1803 																data = anco.text().toLatin1();
1804 															QByteArray decomdata;
1805 															if (anco.hasAttribute("uni:compressor") && (anco.attribute("uni:compressor") == "zlib/deflate"))
1806 																decomdata = qUncompress(data);
1807 															else
1808 																decomdata = data;
1809 														}
1810 													} */
1811 												}
1812 												else if (stcespt.tagName() == "vt:anchoring-object")
1813 												{
1814 													for (QDomNode anc = stcespt.firstChild(); !anc.isNull(); anc = anc.nextSibling())
1815 													{
1816 														QDomElement anco = anc.toElement();
1817 														if (anco.tagName() == "vo:object")
1818 														{
1819 															PageItem* item = parseObjectXML(anco);
1820 															if (item != nullptr)
1821 															{
1822 																item->isEmbedded = true;
1823 																item->gXpos = 0;
1824 																item->gYpos = 0;
1825 																item->gWidth = item->width();
1826 																item->gHeight = item->height();
1827 																int fIndex = m_Doc->addToInlineFrames(item);
1828 																itemText.insertObject(fIndex);
1829 															}
1830 														}
1831 													}
1832 													count = 1;
1833 												}
1834 												else if (stcespt.tagName() == "vt:tab")
1835 												{
1836 													count = 1;
1837 													itemText.insertChars(posC, SpecialChars::TAB);
1838 												}
1839 												if (count != 0)
1840 												{
1841 													itemText.applyStyle(posC, tmpStyle);
1842 													itemText.applyCharStyle(posC, count, tmpCStyle);
1843 												}
1844 												posC = itemText.length();
1845 											}
1846 										}
1847 									}
1848 									if (stce.attribute("vt:break") == "paragraph-break")
1849 										itemText.insertChars(posC, SpecialChars::PARSEP);
1850 									else if (stce.attribute("vt:break") == "layout-column-break")
1851 										itemText.insertChars(posC, SpecialChars::COLBREAK);
1852 									else if (stce.attribute("vt:break") == "area-break")
1853 										itemText.insertChars(posC, SpecialChars::FRAMEBREAK);
1854 									else
1855 										itemText.insertChars(posC, SpecialChars::PARSEP);
1856 									itemText.applyStyle(posC, tmpStyle);
1857 									posC = itemText.length();
1858 								}
1859 							}
1860 						}
1861 					}
1862 				}
1863 			}
1864 		}
1865 	}
1866 }
1867 
parseAttributeSetXML(const QDomElement & obNode,AttributeSet & attrs)1868 void VivaPlug::parseAttributeSetXML(const QDomElement& obNode, AttributeSet &attrs)
1869 {
1870 	if (obNode.tagName() == "vs:template")
1871 		attrs.parentStyle = obNode.text();
1872 	for (QDomNode stx = obNode.firstChild(); !stx.isNull(); stx = stx.nextSibling())
1873 	{
1874 		QDomElement stxe = stx.toElement();
1875 		if (stxe.tagName() == "vta:font")
1876 		{
1877 			if (stxe.hasAttribute("vta:family"))
1878 				attrs.fontFamily = AttributeValue(stxe.attribute("vta:family"));
1879 			if (stxe.hasAttribute("vta:style"))
1880 				attrs.fontStyle = AttributeValue(stxe.attribute("vta:style"));
1881 		}
1882 		else if (stxe.tagName() == "vta:font-size")
1883 		{
1884 			if (stxe.hasAttribute("vta:value"))
1885 				attrs.fontSize = AttributeValue(stxe.attribute("vta:value"));
1886 		}
1887 		else if (stxe.tagName() == "vta:character-color")
1888 		{
1889 			if (stxe.hasAttribute("vta:name"))
1890 				attrs.fontColor = AttributeValue(colorTranslate[stxe.attribute("vta:name")]);
1891 		}
1892 		else if (stxe.tagName() == "vta:character-color-density")
1893 		{
1894 			if (stxe.hasAttribute("vta:value"))
1895 				attrs.fontColorDensity = AttributeValue(stxe.attribute("vta:value"));
1896 		}
1897 		else if (stxe.tagName() == "vta:character-type")
1898 		{
1899 			if (stxe.hasAttribute("vta:type"))
1900 				attrs.fontEffect = AttributeValue(stxe.attribute("vta:type"));
1901 		}
1902 		else if (stxe.tagName() == "vta:character-placement")
1903 		{
1904 			if (stxe.hasAttribute("vta:type"))
1905 				attrs.placement = AttributeValue(stxe.attribute("vta:type"));
1906 		}
1907 		else if (stxe.tagName() == "vta:underline")
1908 		{
1909 			attrs.underline = AttributeValue("true");
1910 			attrs.underlineOffset = AttributeValue(stxe.attribute("vta:offset"));
1911 			QDomNode ul = stxe.firstChild();
1912 			if (!ul.isNull())
1913 			{
1914 				QDomElement ule = ul.toElement();
1915 				if (ule.tagName() == "vta:pen")
1916 					attrs.underlineWidth = AttributeValue(ule.attribute("vta:width"));
1917 			}
1918 		}
1919 		else if (stxe.tagName() == "vta:strikethrough")
1920 		{
1921 			attrs.strikethrough = AttributeValue("true");
1922 			attrs.strikethroughOffset = AttributeValue(stxe.attribute("vta:offset"));
1923 			QDomNode ul = stxe.firstChild();
1924 			if (!ul.isNull())
1925 			{
1926 				QDomElement ule = ul.toElement();
1927 				if (ule.tagName() == "vta:pen")
1928 					attrs.strikethroughWidth = AttributeValue(ule.attribute("vta:width"));
1929 			}
1930 		}
1931 		else if (stxe.tagName() == "vta:character-outline")
1932 		{
1933 			if (stxe.attribute("vta:active") == "true")
1934 			{
1935 				attrs.outline = AttributeValue("true");
1936 				QDomNode ul = stxe.firstChild();
1937 				if (!ul.isNull())
1938 				{
1939 					QDomElement ule = ul.toElement();
1940 					if (ule.tagName() == "vta:pen")
1941 					{
1942 						attrs.outlineWidth = AttributeValue(ule.attribute("vta:width"));
1943 						attrs.outlineColor = AttributeValue(colorTranslate[ule.attribute("vta:color")]);
1944 					}
1945 				}
1946 			}
1947 		}
1948 		else if (stxe.tagName() == "vta:character-width-scale")
1949 		{
1950 			if (stxe.hasAttribute("vta:value"))
1951 				attrs.widthScale = AttributeValue(stxe.attribute("vta:value"));
1952 		}
1953 		else if (stxe.tagName() == "vta:character-height-scale")
1954 		{
1955 			if (stxe.hasAttribute("vta:value"))
1956 				attrs.heightScale = AttributeValue(stxe.attribute("vta:value"));
1957 		}
1958 		else if ((stxe.tagName() == "vta:character-spacing") || (stxe.tagName() == "vta:kerning"))
1959 		{
1960 			if (stxe.hasAttribute("vta:value"))
1961 				attrs.spacing = AttributeValue(stxe.attribute("vta:value"));
1962 		}
1963 		else if (stxe.tagName() == "vta:baseline-shift")
1964 		{
1965 			if (stxe.hasAttribute("vta:value"))
1966 				attrs.baselineOffset = AttributeValue(stxe.attribute("vta:value"));
1967 		}
1968 		else if (stxe.tagName() == "vta:writing-justification")
1969 		{
1970 			if (stxe.hasAttribute("vta:value"))
1971 				attrs.justification = AttributeValue(stxe.attribute("vta:value"));
1972 		}
1973 		else if (stxe.tagName() == "vta:paragraph-distance-before")
1974 		{
1975 			if (stxe.hasAttribute("vta:value"))
1976 				attrs.gapbefore = AttributeValue(stxe.attribute("vta:value"));
1977 		}
1978 		else if (stxe.tagName() == "vta:paragraph-distance-after")
1979 		{
1980 			if (stxe.hasAttribute("vta:value"))
1981 				attrs.gapafter = AttributeValue(stxe.attribute("vta:value"));
1982 		}
1983 		else if (stxe.tagName() == "vta:line-distance")
1984 		{
1985 			if (stxe.hasAttribute("vta:value"))
1986 				attrs.lineSpacing = AttributeValue(stxe.attribute("vta:value"));
1987 		}
1988 		else if (stxe.tagName() == "vta:paragraph-indent")
1989 		{
1990 			if (stxe.hasAttribute("vta:value"))
1991 				attrs.firstLineIndent = AttributeValue(stxe.attribute("vta:value"));
1992 		}
1993 		else if (stxe.tagName() == "vta:paragraph-begin-indent")
1994 		{
1995 			if (stxe.hasAttribute("vta:value"))
1996 				attrs.indent = AttributeValue(stxe.attribute("vta:value"));
1997 		}
1998 		else if (stxe.tagName() == "vta:paragraph-end-indent")
1999 		{
2000 			if (stxe.hasAttribute("vta:value"))
2001 				attrs.rightIndent = AttributeValue(stxe.attribute("vta:value"));
2002 		}
2003 		else if (stxe.tagName() == "vta:layout-columns")
2004 		{
2005 			int columnCount = 0;
2006 			double columnGutter = 0.0;
2007 			for (QDomNode stc = stxe.firstChild(); !stc.isNull(); stc = stc.nextSibling())
2008 			{
2009 				QDomElement stce = stc.toElement();
2010 				if (stce.tagName() == "vta:column")
2011 				{
2012 					columnCount++;
2013 					columnGutter = qMax(columnGutter, parseUnit(stce.attribute("vta:gutter", "0")));
2014 				}
2015 			}
2016 			if (columnCount > 0)
2017 			{
2018 				attrs.columnCount = AttributeValue(QString("%1").arg(columnCount));
2019 				attrs.columnGutter = AttributeValue(QString("%1").arg(columnGutter));
2020 			}
2021 		}
2022 		else if (stxe.tagName() == "vta:initials")
2023 		{
2024 			if (stxe.attribute("vta:active") == "true")
2025 			{
2026 				attrs.dropCaps = AttributeValue("true");
2027 				attrs.dropCapsDist = AttributeValue(stxe.attribute("vta:distance-to-text", "0"));
2028 				for (QDomNode stc = stxe.firstChild(); !stc.isNull(); stc = stc.nextSibling())
2029 				{
2030 					QDomElement stce = stc.toElement();
2031 					if (stce.tagName() == "vta:size")
2032 					{
2033 						QDomNode ul = stce.firstChild();
2034 						if (!ul.isNull())
2035 						{
2036 							QDomElement ule = ul.toElement();
2037 							if (ule.tagName() == "vta:dynamic-lines")
2038 							{
2039 								attrs.dropCapsLines = AttributeValue(ule.attribute("vta:maximum-lines", "1"));
2040 							}
2041 						}
2042 					}
2043 				}
2044 			}
2045 		}
2046 		else if (stxe.tagName() == "vta:tabulators")
2047 		{
2048 			QString tabs = "";
2049 			for (QDomNode stc = stxe.firstChild(); !stc.isNull(); stc = stc.nextSibling())
2050 			{
2051 				QDomElement stce = stc.toElement();
2052 				if (stce.tagName() == "vta:tabulator")
2053 				{
2054 					if (stce.hasAttribute("vta:position"))
2055 						tabs += stce.attribute("vta:position");
2056 					tabs += "\t";
2057 					if (stce.hasAttribute("vta:alignment"))
2058 						tabs += stce.attribute("vta:alignment");
2059 					tabs += "\t";
2060 					if (stce.hasAttribute("vta:filler"))
2061 						tabs += stce.attribute("vta:filler");
2062 				}
2063 				tabs += "\n";
2064 			}
2065 			attrs.tabulators = AttributeValue(tabs);
2066 		}
2067 	}
2068 	if ((attrs.fontFamily.valid) && (attrs.fontStyle.valid))
2069 		attrs.fontFullName = AttributeValue(constructFontName(attrs.fontFamily.value, attrs.fontStyle.value));
2070 }
2071 
parseAttributeSetsXML(const QDomElement & obNode)2072 void VivaPlug::parseAttributeSetsXML(const QDomElement& obNode)
2073 {
2074 	for (QDomNode spo = obNode.firstChild(); !spo.isNull(); spo = spo.nextSibling())
2075 	{
2076 		QDomElement eo = spo.toElement();
2077 		AttributeSet attrs;
2078 		parseAttributeSetXML(eo, attrs);
2079 		if (eo.hasAttribute("vs:paragraph-style"))
2080 			attrs.applyedParStyle = AttributeValue(eo.attribute("vs:paragraph-style"));
2081 		AttributeSets.insert(eo.attribute("vs:name"), attrs);
2082 	}
2083 }
2084 
parseStylesheetsXML(const QDomElement & obNode)2085 void VivaPlug::parseStylesheetsXML(const QDomElement& obNode)
2086 {
2087 	for (QDomNode spo = obNode.firstChild(); !spo.isNull(); spo = spo.nextSibling())
2088 	{
2089 		QDomElement eo = spo.toElement();
2090 		if (eo.tagName() == "vs:paragraphStylesheet")
2091 		{
2092 			ParagraphStyle newStyle;
2093 			newStyle.erase();
2094 			newStyle.setDefaultStyle(false);
2095 			newStyle.setName(eo.attribute("vs:name"));
2096 			newStyle.setParent(CommonStrings::DefaultParagraphStyle);
2097 			ParagraphStyle ttx = m_Doc->paragraphStyle(CommonStrings::DefaultParagraphStyle);
2098 			CharStyle nstyle = ttx.charStyle();
2099 			newStyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
2100 			newStyle.setLineSpacing(nstyle.fontSize() / 10.0);
2101 			AttributeSet attrs;
2102 			for (QDomNode stx = eo.firstChild(); !stx.isNull(); stx = stx.nextSibling())
2103 			{
2104 				QDomElement stxe = stx.toElement();
2105 				parseAttributeSetXML(stxe, attrs);
2106 			}
2107 			applyParagraphAttrs(newStyle, attrs);
2108 			applyCharacterAttrs(newStyle.charStyle(), newStyle, attrs);
2109 			StyleSet<ParagraphStyle>tmp;
2110 			tmp.create(newStyle);
2111 			m_Doc->redefineStyles(tmp, false);
2112 		}
2113 	}
2114 }
2115 
applyParagraphAttrs(ParagraphStyle & newStyle,AttributeSet & pAttrs)2116 void VivaPlug::applyParagraphAttrs(ParagraphStyle &newStyle, AttributeSet &pAttrs)
2117 {
2118 	if (pAttrs.applyedParStyle.valid)
2119 		newStyle = m_Doc->paragraphStyle(pAttrs.applyedParStyle.value);
2120 	if (pAttrs.parentStyle.valid)
2121 		newStyle.setParent(pAttrs.parentStyle.value);
2122 	if (pAttrs.justification.valid)
2123 	{
2124 		if (pAttrs.justification.value == "left")
2125 			newStyle.setAlignment(ParagraphStyle::LeftAligned);
2126 		else if (pAttrs.justification.value == "right")
2127 			newStyle.setAlignment(ParagraphStyle::RightAligned);
2128 		else if (pAttrs.justification.value == "center")
2129 			newStyle.setAlignment(ParagraphStyle::Centered);
2130 		else if (pAttrs.justification.value == "justified")
2131 			newStyle.setAlignment(ParagraphStyle::Justified);
2132 		else if (pAttrs.justification.value == "forced-justified")
2133 			newStyle.setAlignment(ParagraphStyle::Extended);
2134 	}
2135 	if (pAttrs.gapbefore.valid)
2136 		newStyle.setGapBefore(parseUnit(pAttrs.gapbefore.value));
2137 	if (pAttrs.gapafter.valid)
2138 		newStyle.setGapAfter(parseUnit(pAttrs.gapafter.value));
2139 	if (pAttrs.lineSpacing.valid)
2140 	{
2141 		newStyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
2142 		newStyle.setLineSpacing(parseUnit(pAttrs.lineSpacing.value));
2143 	}
2144 	else
2145 		newStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
2146 	if (pAttrs.firstLineIndent.valid)
2147 		newStyle.setFirstIndent(parseUnit(pAttrs.firstLineIndent.value));
2148 	if (pAttrs.indent.valid)
2149 	{
2150 		newStyle.setLeftMargin(parseUnit(pAttrs.indent.value));
2151 		newStyle.setFirstIndent(newStyle.firstIndent() - parseUnit(pAttrs.indent.value));
2152 	}
2153 	if (pAttrs.rightIndent.valid)
2154 		newStyle.setRightMargin(parseUnit(pAttrs.rightIndent.value));
2155 	if (pAttrs.dropCaps.valid)
2156 	{
2157 		newStyle.setHasDropCap(true);
2158 		if (pAttrs.dropCapsLines.valid)
2159 			newStyle.setDropCapLines(pAttrs.dropCapsLines.value.toInt());
2160 		if (pAttrs.dropCapsDist.valid)
2161 			newStyle.setParEffectOffset(parseUnit(pAttrs.dropCapsDist.value));
2162 	}
2163 	if (pAttrs.tabulators.valid)
2164 	{
2165 		QList<ParagraphStyle::TabRecord> tbs;
2166 		newStyle.resetTabValues();
2167 		QStringList tabList = pAttrs.tabulators.value.split("\n");
2168 		for (int a = 0; a < tabList.count(); a++)
2169 		{
2170 			QString tbv = tabList[a];
2171 			if (!tbv.isEmpty())
2172 			{
2173 				ParagraphStyle::TabRecord tb;
2174 				QStringList tab = tbv.split("\t");
2175 				tb.tabPosition = parseUnit(tab[0]);
2176 				tb.tabType = 0;
2177 				if (tab[1] == "begin")
2178 					tb.tabType = 0;
2179 				else if (tab[1] == "center")
2180 					tb.tabType = 4;
2181 				else if (tab[1] == "end")
2182 					tb.tabType = 1;
2183 				else if (tab[1] == "character")
2184 					tb.tabType = 3;
2185 				tb.tabFillChar = tab[2].isEmpty() ? QChar() : tab[2][0];
2186 				tbs.append(tb);
2187 			}
2188 		}
2189 		if (tbs.count() > 0)
2190 			newStyle.setTabValues(tbs);
2191 	}
2192 }
2193 
applyCharacterAttrs(CharStyle & tmpCStyle,ParagraphStyle & newStyle,AttributeSet & pAttrs)2194 void VivaPlug::applyCharacterAttrs(CharStyle &tmpCStyle, ParagraphStyle &newStyle, AttributeSet &pAttrs)
2195 {
2196 	if (pAttrs.fontSize.valid)
2197 	{
2198 		tmpCStyle.setFontSize(pAttrs.fontSize.value.toDouble() * 10);
2199 		if (pAttrs.lineSpacing.valid)
2200 		{
2201 			if (pAttrs.fontSize.value.toInt() > parseUnit(pAttrs.lineSpacing.value))
2202 				newStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
2203 		}
2204 	}
2205 	if (pAttrs.fontFullName.valid)
2206 		tmpCStyle.setFont((*m_Doc->AllFonts)[pAttrs.fontFullName.value]);
2207 	if (pAttrs.fontColor.valid)
2208 		tmpCStyle.setFillColor(pAttrs.fontColor.value);
2209 	if (pAttrs.fontColorDensity.valid)
2210 	{
2211 		int tint = 100;
2212 		if (pAttrs.fontColorDensity.value == "transparent")
2213 			tint = 0;
2214 		else
2215 			tint = pAttrs.fontColorDensity.value.toInt();
2216 		tmpCStyle.setFillShade(tint);
2217 	}
2218 	if (pAttrs.underline.valid)
2219 	{
2220 		if (pAttrs.underlineWidth.valid)
2221 			tmpCStyle.setUnderlineWidth(qRound(parseUnit(pAttrs.underlineWidth.value) * 1000 / (tmpCStyle.fontSize() / 10.0)));
2222 		else
2223 			tmpCStyle.setUnderlineWidth(-1);
2224 		if (pAttrs.underlineOffset.valid)
2225 		{
2226 			if (parseUnit(pAttrs.underlineOffset.value) != 0)
2227 				tmpCStyle.setUnderlineOffset(qRound(parseUnit(pAttrs.underlineOffset.value) * 1000 / (tmpCStyle.fontSize() / 10.0)));
2228 			else
2229 				tmpCStyle.setUnderlineOffset(-1);
2230 		}
2231 		else
2232 			tmpCStyle.setUnderlineOffset(-1);
2233 		StyleFlag styleEffects = tmpCStyle.effects();
2234 		styleEffects |= ScStyle_Underline;
2235 		tmpCStyle.setFeatures(styleEffects.featureList());
2236 	}
2237 	if (pAttrs.strikethrough.valid)
2238 	{
2239 		if (pAttrs.strikethroughWidth.valid)
2240 			tmpCStyle.setStrikethruWidth(qRound(parseUnit(pAttrs.strikethroughWidth.value) * 1000 / (tmpCStyle.fontSize() / 10.0)));
2241 		else
2242 			tmpCStyle.setStrikethruWidth(-1);
2243 		if (pAttrs.strikethroughOffset.valid)
2244 		{
2245 			if (parseUnit(pAttrs.strikethroughOffset.value) != 0)
2246 				tmpCStyle.setStrikethruOffset(qRound(parseUnit(pAttrs.strikethroughOffset.value) * 1000 / (tmpCStyle.fontSize() / 10.0)));
2247 			else
2248 				tmpCStyle.setStrikethruOffset(-1);
2249 		}
2250 		else
2251 			tmpCStyle.setStrikethruOffset(-1);
2252 		StyleFlag styleEffects = tmpCStyle.effects();
2253 		styleEffects |= ScStyle_Strikethrough;
2254 		tmpCStyle.setFeatures(styleEffects.featureList());
2255 	}
2256 	if (pAttrs.outline.valid)
2257 	{
2258 		if (pAttrs.outlineWidth.valid)
2259 			tmpCStyle.setOutlineWidth(qRound(parseUnit(pAttrs.outlineWidth.value) * 1000 / (tmpCStyle.fontSize() / 10.0)));
2260 		else
2261 			tmpCStyle.setOutlineWidth(-1);
2262 		if (pAttrs.outlineColor.valid)
2263 			tmpCStyle.setStrokeColor(pAttrs.outlineColor.value);
2264 		StyleFlag styleEffects = tmpCStyle.effects();
2265 		styleEffects |= ScStyle_Outline;
2266 		tmpCStyle.setFeatures(styleEffects.featureList());
2267 	}
2268 	if (pAttrs.placement.valid)
2269 	{
2270 		StyleFlag styleEffects = tmpCStyle.effects();
2271 		if ((pAttrs.placement.value == "superscript") || (pAttrs.placement.value == "index"))
2272 			styleEffects |= ScStyle_Superscript;
2273 		else if (pAttrs.placement.value == "subscript")
2274 			styleEffects |= ScStyle_Subscript;
2275 		tmpCStyle.setFeatures(styleEffects.featureList());
2276 	}
2277 	if (pAttrs.fontEffect.valid)
2278 	{
2279 		StyleFlag styleEffects = tmpCStyle.effects();
2280 		if (pAttrs.fontEffect.value == "caps")
2281 			styleEffects |= ScStyle_AllCaps;
2282 		else if (pAttrs.fontEffect.value == "small-caps")
2283 			styleEffects |= ScStyle_SmallCaps;
2284 		tmpCStyle.setFeatures(styleEffects.featureList());
2285 	}
2286 	if (pAttrs.widthScale.valid)
2287 		tmpCStyle.setScaleH(pAttrs.widthScale.value.toInt() * 10);
2288 	if (pAttrs.heightScale.valid)
2289 		tmpCStyle.setScaleV(pAttrs.heightScale.value.toInt() * 10);
2290 	if (pAttrs.spacing.valid)
2291 		tmpCStyle.setTracking(pAttrs.spacing.value.toInt() * 10);
2292 	if (pAttrs.baselineOffset.valid)
2293 	{
2294 		if (parseUnit(pAttrs.baselineOffset.value) != 0)
2295 			tmpCStyle.setBaselineOffset(qRound(parseUnit(pAttrs.baselineOffset.value) * 1000 / (tmpCStyle.fontSize() / 10.0)));
2296 	}
2297 }
2298 
constructFontName(const QString & fontBaseName,const QString & fontStyle)2299 QString VivaPlug::constructFontName(const QString& fontBaseName, const QString& fontStyle)
2300 {
2301 	QString fontName = "";
2302 	bool found = false;
2303 	SCFontsIterator it(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts);
2304 	for ( ; it.hasNext(); it.next())
2305 	{
2306 		if (fontBaseName.toLower() == it.current().family().toLower())
2307 		{
2308 			// found the font family, now go for the style
2309 			QStringList slist = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.fontMap[it.current().family()];
2310 			slist.sort();
2311 			if (slist.count() > 0)
2312 			{
2313 				for (int a = 0; a < slist.count(); a++)
2314 				{
2315 					if (fontStyle.toLower() == slist[a].toLower())
2316 					{
2317 						found = true;
2318 						fontName = it.current().family() + " " + slist[a];
2319 						break;
2320 					}
2321 				}
2322 				if (!found)
2323 				{
2324 					int reInd = slist.indexOf("Regular");
2325 					if (reInd < 0)
2326 						fontName = it.current().family() + " " + slist[0];
2327 					else
2328 						fontName = it.current().family() + " " + slist[reInd];
2329 					found = true;
2330 				}
2331 			}
2332 			else
2333 			{
2334 				fontName = it.current().family();
2335 				found = true;
2336 			}
2337 			break;
2338 		}
2339 	}
2340 	if (!found)
2341 	{
2342 		if (importerFlags & LoadSavePlugin::lfCreateThumbnail)
2343 			fontName = PrefsManager::instance().appPrefs.itemToolPrefs.textFont;
2344 		else
2345 		{
2346 			QString family = fontBaseName;
2347 			if (!fontStyle.isEmpty())
2348 				family += " " + fontStyle;
2349 			if (!PrefsManager::instance().appPrefs.fontPrefs.GFontSub.contains(family))
2350 			{
2351 				qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
2352 				MissingFont *dia = new MissingFont(nullptr, family, m_Doc);
2353 				dia->exec();
2354 				fontName = dia->getReplacementFont();
2355 				delete dia;
2356 				qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
2357 				PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family] = fontName;
2358 			}
2359 			else
2360 				fontName = PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family];
2361 		}
2362 	}
2363 	return fontName;
2364 }
2365 
intersectBoundingRect(PageItem * item,QLineF gradientVector)2366 QPointF VivaPlug::intersectBoundingRect(PageItem *item, QLineF gradientVector)
2367 {
2368 	QPointF interPoint;
2369 	QPointF gradEnd;
2370 	if (gradientVector.intersects(QLineF(0, 0, item->width(), 0), &interPoint) == QLineF::BoundedIntersection)
2371 		gradEnd = interPoint;
2372 	else if (gradientVector.intersects(QLineF(item->width(), 0, item->width(), item->height()), &interPoint) == QLineF::BoundedIntersection)
2373 		gradEnd = interPoint;
2374 	else if (gradientVector.intersects(QLineF(item->width(), item->height(), 0, item->height()), &interPoint) == QLineF::BoundedIntersection)
2375 		gradEnd = interPoint;
2376 	else if (gradientVector.intersects(QLineF(0, item->height(), 0, 0), &interPoint) == QLineF::BoundedIntersection)
2377 		gradEnd = interPoint;
2378 	return gradEnd;
2379 }
2380