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 #include <QByteArray>
9 #include <QCursor>
10 #include <QDrag>
11 #include <QFile>
12 #include <QList>
13 #include <QMimeData>
14 #include <QRegExp>
15 #include <QStack>
16 #include <QDebug>
17 
18 #include <cstdlib>
19 
20 #include "importshape.h"
21 
22 
23 #include "commonstrings.h"
24 #include "loadsaveplugin.h"
25 #include "pagesize.h"
26 #include "prefscontext.h"
27 #include "prefsfile.h"
28 #include "prefsmanager.h"
29 #include "prefstable.h"
30 #include "rawimage.h"
31 #include "scclocale.h"
32 #include "sccolorengine.h"
33 #include "scconfig.h"
34 #include "sclimits.h"
35 #include "scmimedata.h"
36 #include "scpaths.h"
37 #include "scribusXml.h"
38 #include "scribuscore.h"
39 #include "scribusdoc.h"
40 #include "scribusview.h"
41 #include "sctextstream.h"
42 #include "selection.h"
43 #include "ui/customfdialog.h"
44 #include "ui/missing.h"
45 #include "ui/multiprogressdialog.h"
46 #include "ui/propertiespalette.h"
47 #include "undomanager.h"
48 #include "units.h"
49 #include "util.h"
50 #include "util_formats.h"
51 #include "util_math.h"
52 
ShapePlug(ScribusDoc * doc,int flags)53 ShapePlug::ShapePlug(ScribusDoc* doc, int flags)
54 {
55 	tmpSel=new Selection(this, false);
56 	m_Doc=doc;
57 	importerFlags = flags;
58 	interactive = (flags & LoadSavePlugin::lfInteractive);
59 	progressDialog = nullptr;
60 }
61 
readThumbnail(const QString & fName)62 QImage ShapePlug::readThumbnail(const QString& fName)
63 {
64 	QFileInfo fi = QFileInfo(fName);
65 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
66 	double b = 0.0, h = 0.0;
67 	parseHeader(fName, b, h);
68 	if (b == 0.0)
69 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
70 	if (h == 0.0)
71 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
72 	docWidth = b;
73 	docHeight = h;
74 	progressDialog = nullptr;
75 	m_Doc = new ScribusDoc();
76 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
77 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
78 	m_Doc->addPage(0);
79 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
80 	baseX = m_Doc->currentPage()->xOffset();
81 	baseY = m_Doc->currentPage()->yOffset();
82 	Elements.clear();
83 	m_Doc->setLoading(true);
84 	m_Doc->DoDrawing = false;
85 	m_Doc->scMW()->setScriptRunning(true);
86 	QString CurDirP = QDir::currentPath();
87 	QDir::setCurrent(fi.path());
88 	if (convert(fName))
89 	{
90 		tmpSel->clear();
91 		QDir::setCurrent(CurDirP);
92 		if (Elements.count() > 1)
93 			m_Doc->groupObjectsList(Elements);
94 		m_Doc->DoDrawing = true;
95 		m_Doc->m_Selection->delaySignalsOn();
96 		QImage tmpImage;
97 		if (Elements.count() > 0)
98 		{
99 			for (int dre=0; dre<Elements.count(); ++dre)
100 			{
101 				tmpSel->addItem(Elements.at(dre), true);
102 			}
103 			tmpSel->setGroupRect();
104 			double xs = tmpSel->width();
105 			double ys = tmpSel->height();
106 			tmpImage = Elements.at(0)->DrawObj_toImage(500);
107 			tmpImage.setText("XSize", QString("%1").arg(xs));
108 			tmpImage.setText("YSize", QString("%1").arg(ys));
109 		}
110 		m_Doc->scMW()->setScriptRunning(false);
111 		m_Doc->setLoading(false);
112 		m_Doc->m_Selection->delaySignalsOff();
113 		delete m_Doc;
114 		return tmpImage;
115 	}
116 	QDir::setCurrent(CurDirP);
117 	m_Doc->DoDrawing = true;
118 	m_Doc->scMW()->setScriptRunning(false);
119 	delete m_Doc;
120 	return QImage();
121 }
122 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)123 bool ShapePlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
124 {
125 	bool success = false;
126 	interactive = (flags & LoadSavePlugin::lfInteractive);
127 	importerFlags = flags;
128 	cancel = false;
129 //	double x, y, b, h;
130 	double b, h;
131 	bool ret = false;
132 	QFileInfo fi = QFileInfo(fNameIn);
133 	if ( !ScCore->usingGUI() )
134 	{
135 		interactive = false;
136 		showProgress = false;
137 	}
138 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
139 	if ( showProgress )
140 	{
141 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
142 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
143 		QStringList barNames, barTexts;
144 		barNames << "GI";
145 		barTexts << tr("Analyzing File:");
146 		QList<bool> barsNumeric;
147 		barsNumeric << false;
148 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
149 		progressDialog->setOverallTotalSteps(3);
150 		progressDialog->setOverallProgress(0);
151 		progressDialog->setProgress("GI", 0);
152 		progressDialog->show();
153 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
154 		qApp->processEvents();
155 	}
156 	else
157 		progressDialog = nullptr;
158 /* Set default Page to size defined in Preferences */
159 //	x = 0.0;
160 //	y = 0.0;
161 	b = 0.0;
162 	h = 0.0;
163 	if (progressDialog)
164 	{
165 		progressDialog->setOverallProgress(1);
166 		qApp->processEvents();
167 	}
168 	parseHeader(fNameIn, b, h);
169 	if (b == 0.0)
170 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
171 	if (h == 0.0)
172 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
173 	docWidth = b;
174 	docHeight = h;
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();
196 		}
197 	}
198 	if ((!ret) && (interactive))
199 	{
200 		baseX = m_Doc->currentPage()->xOffset();
201 		baseY = m_Doc->currentPage()->yOffset();
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 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
212 		m_Doc->view()->deselectItems();
213 	Elements.clear();
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 				m_Doc->m_Selection->delaySignalsOff();
268 				// We must copy the TransationSettings object as it is owned
269 				// by handleObjectImport method afterwards
270 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
271 				m_Doc->view()->handleObjectImport(md, transacSettings);
272 				m_Doc->DragP = false;
273 				m_Doc->DraggedElem = nullptr;
274 				m_Doc->DragElements.clear();
275 			}
276 		}
277 		else
278 		{
279 			m_Doc->changed();
280 			m_Doc->reformPages();
281 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
282 				m_Doc->view()->updatesOn(true);
283 		}
284 		success = true;
285 	}
286 	else
287 	{
288 		QDir::setCurrent(CurDirP);
289 		m_Doc->DoDrawing = true;
290 		m_Doc->scMW()->setScriptRunning(false);
291 		if (!(flags & LoadSavePlugin::lfLoadAsPattern))
292 			m_Doc->view()->updatesOn(true);
293 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
294 	}
295 	if (interactive)
296 		m_Doc->setLoading(false);
297 	//CB If we have a gui we must refresh it if we have used the progressbar
298 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
299 	{
300 		if ((showProgress) && (!interactive))
301 			m_Doc->view()->DrawNew();
302 	}
303 	qApp->restoreOverrideCursor();
304 	return success;
305 }
306 
~ShapePlug()307 ShapePlug::~ShapePlug()
308 {
309 	delete progressDialog;
310 	delete tmpSel;
311 }
312 
parseHeader(const QString & fName,double & b,double & h)313 void ShapePlug::parseHeader(const QString& fName, double &b, double &h)
314 {
315 	QFile f(fName);
316 	if (f.open(QIODevice::ReadOnly))
317 	{
318 		double minXCoor = 0.0;
319 		double minYCoor = 0.0;
320 		double maxXCoor = 0.0;
321 		double maxYCoor = 0.0;
322 		QDomDocument docu("scridoc");
323 		docu.setContent(&f);
324 		QDomElement elem = docu.documentElement();
325 		QDomNodeList list = elem.elementsByTagName("svg:svg");
326 		if (list.count() == 0)
327 			return;
328 		QDomElement svg = list.item(0).toElement();
329 		QDomNode DOC = svg.firstChild();
330 		Conversion = 1.0;
331 		bool firstCheck = true;
332 		parseGroupProperties(DOC, minXCoor, minYCoor, maxXCoor, maxYCoor, firstCheck);
333 		b = maxXCoor - minXCoor;
334 		h = maxYCoor - minYCoor;
335 		Conversion = 100.0 / qMax(b, h);
336 		b *= Conversion;
337 		h *= Conversion;
338 		f.close();
339 	}
340 }
341 
convert(const QString & fn)342 bool ShapePlug::convert(const QString& fn)
343 {
344 	importedColors.clear();
345 	QList<PageItem*> gElements;
346 	groupStack.push(gElements);
347 	if (progressDialog)
348 	{
349 		progressDialog->setOverallProgress(2);
350 		progressDialog->setLabel("GI", tr("Generating Items"));
351 		qApp->processEvents();
352 	}
353 	QFile f(fn);
354 	if (f.open(QIODevice::ReadOnly))
355 	{
356 		QDomDocument docu("scridoc");
357 		docu.setContent(&f);
358 		QDomElement elem = docu.documentElement();
359 		if (elem.tagName() != "shape")
360 			return false;
361 		QDomNodeList list = elem.elementsByTagName("svg:svg");
362 		if (list.count() == 0)
363 			return false;
364 		QDomElement svg = list.item(0).toElement();
365 		QDomNode DOC = svg.firstChild();
366 		parseGroup(DOC);
367 		if (Elements.count() == 0)
368 		{
369 			if (importedColors.count() != 0)
370 			{
371 				for (int cd = 0; cd < importedColors.count(); cd++)
372 				{
373 					m_Doc->PageColors.remove(importedColors[cd]);
374 				}
375 			}
376 		}
377 		f.close();
378 	}
379 	if (progressDialog)
380 		progressDialog->close();
381 	return true;
382 }
383 
finishItem(PageItem * ite)384 void ShapePlug::finishItem(PageItem* ite)
385 {
386 	ite->ClipEdited = true;
387 	ite->FrameType = 3;
388 	ite->setFillShade(100);
389 	ite->setLineShade(100);
390 	ite->setTextFlowMode(PageItem::TextFlowDisabled);
391 	ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
392 	m_Doc->adjustItemSize(ite);
393 	ite->OldB2 = ite->width();
394 	ite->OldH2 = ite->height();
395 	ite->updateClip();
396 	Elements.append(ite);
397 	if (groupStack.count() > 0)
398 		groupStack.top().append(ite);
399 }
400 
parseGroup(QDomNode & DOC)401 void ShapePlug::parseGroup(QDomNode &DOC)
402 {
403 	QString FillCol = "White";
404 	QString StrokeCol = "Black";
405 	QString defFillCol = "White";
406 	QString defStrokeCol = "Black";
407 	QColor stroke = Qt::black;
408 	QColor fill = Qt::white;
409 //	Qt::PenStyle Dash = Qt::SolidLine;
410 	Qt::PenCapStyle LineEnd = Qt::FlatCap;
411 	Qt::PenJoinStyle LineJoin = Qt::MiterJoin;
412 //	int fillStyle = 1;
413 	double strokewidth = 0.1;
414 //	bool poly = false;
415 	while (!DOC.isNull())
416 	{
417 		double x1, y1, x2, y2;
418 		StrokeCol = defStrokeCol;
419 		FillCol = defFillCol;
420 		stroke = Qt::black;
421 		fill = Qt::white;
422 	//	fillStyle = 1;
423 		strokewidth = 1.0;
424 	//	Dash = Qt::SolidLine;
425 		LineEnd = Qt::FlatCap;
426 		LineJoin = Qt::MiterJoin;
427 		FPointArray PoLine;
428 		PoLine.resize(0);
429 		QDomElement pg = DOC.toElement();
430 		QString STag = pg.tagName();
431 		QString style = pg.attribute( "style", "" ).simplified();
432 		if (style.isEmpty())
433 			style = pg.attribute( "svg:style", "" ).simplified();
434 		QStringList substyles = style.split(';', Qt::SkipEmptyParts);
435 		for (QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it)
436 		{
437 			QStringList substyle = (*it).split(':', Qt::SkipEmptyParts);
438 			QString command(substyle[0].trimmed());
439 			QString params(substyle[1].trimmed());
440 			if (command == "fill")
441 			{
442 				if (!((params == "foreground") || (params == "background") || (params == "fg") || (params == "bg") || (params == "none") || (params == "default") || (params == "inverse")))
443 				{
444 					if (params == "nofill")
445 						FillCol = CommonStrings::None;
446 					else
447 					{
448 						fill.setNamedColor( params );
449 						FillCol = "FromDia"+fill.name();
450 						ScColor tmp;
451 						tmp.fromQColor(fill);
452 						tmp.setSpotColor(false);
453 						tmp.setRegistrationColor(false);
454 						QString fNam = m_Doc->PageColors.tryAddColor(FillCol, tmp);
455 						if (fNam == FillCol)
456 							importedColors.append(FillCol);
457 						FillCol = fNam;
458 					}
459 				}
460 			}
461 			else if (command == "stroke")
462 			{
463 				if (!((params == "foreground") || (params == "background") || (params == "fg") || (params == "bg") || (params == "none") || (params == "default")) || (params == "inverse"))
464 				{
465 					stroke.setNamedColor( params );
466 					StrokeCol = "FromDia"+stroke.name();
467 					ScColor tmp;
468 					tmp.fromQColor(stroke);
469 					tmp.setSpotColor(false);
470 					tmp.setRegistrationColor(false);
471 					QString fNam = m_Doc->PageColors.tryAddColor(StrokeCol, tmp);
472 					if (fNam == StrokeCol)
473 						importedColors.append(StrokeCol);
474 					StrokeCol = fNam;
475 				}
476 			}
477 			else if (command == "stroke-width")
478 				strokewidth = ScCLocale::toDoubleC(params);
479 			else if (command == "stroke-linejoin")
480 			{
481 				if (params == "miter")
482 					LineJoin = Qt::MiterJoin;
483 				else if (params == "round")
484 					LineJoin = Qt::RoundJoin;
485 				else if (params == "bevel")
486 					LineJoin = Qt::BevelJoin;
487 			}
488 			else if (command == "stroke-linecap")
489 			{
490 				if (params == "butt")
491 					LineEnd = Qt::FlatCap;
492 				else if (params == "round")
493 					LineEnd = Qt::RoundCap;
494 				else if (params == "square")
495 					LineEnd = Qt::SquareCap;
496 			}
497 		}
498 		if (STag == "svg:line")
499 		{
500 			x1 = ScCLocale::toDoubleC(pg.attribute("x1")) * Conversion;
501 			y1 = ScCLocale::toDoubleC(pg.attribute("y1")) * Conversion;
502 			x2 = ScCLocale::toDoubleC(pg.attribute("x2")) * Conversion;
503 			y2 = ScCLocale::toDoubleC(pg.attribute("y2")) * Conversion;
504 			PoLine.addPoint(x1, y1);
505 			PoLine.addPoint(x1, y1);
506 			PoLine.addPoint(x2, y2);
507 			PoLine.addPoint(x2, y2);
508 			int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, strokewidth, CommonStrings::None, StrokeCol);
509 			m_Doc->Items->at(z)->PoLine = PoLine.copy();
510 			finishItem(m_Doc->Items->at(z));
511 		}
512 		else if (STag == "svg:rect")
513 		{
514 			x1 = ScCLocale::toDoubleC(pg.attribute("x")) * Conversion;
515 			y1 = ScCLocale::toDoubleC(pg.attribute("y")) * Conversion;
516 			x2 = ScCLocale::toDoubleC(pg.attribute("width")) * Conversion;
517 			y2 = ScCLocale::toDoubleC(pg.attribute("height")) * Conversion;
518 			int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + x1, baseY + y1, x2, y2, strokewidth, FillCol, StrokeCol);
519 			m_Doc->Items->at(z)->setLineJoin(LineJoin);
520 			m_Doc->Items->at(z)->setLineEnd(LineEnd);
521 			finishItem(m_Doc->Items->at(z));
522 		}
523 		else if ((STag == "svg:polygon") || (STag == "svg:polyline"))
524 		{
525 			bool bFirst = true;
526 			double x = 0.0;
527 			double y = 0.0;
528 			QString points = pg.attribute( "points" ).simplified().replace(',', " ");
529 			QStringList pointList = points.split(' ', Qt::SkipEmptyParts);
530 			FirstM = true;
531 			for (QStringList::Iterator it = pointList.begin(); it != pointList.end(); it++)
532 			{
533 				x = ScCLocale::toDoubleC(*(it++));
534 				y = ScCLocale::toDoubleC(*it);
535 				if (bFirst)
536 				{
537 					svgMoveTo(x * Conversion, y * Conversion);
538 					bFirst = false;
539 					WasM = true;
540 				}
541 				else
542 				{
543 					svgLineTo(&PoLine, x * Conversion, y * Conversion);
544 				}
545 			}
546 			if (STag == "svg:polygon")
547 				svgClosePath(&PoLine);
548 			if (PoLine.size() < 4)
549 			{
550 				DOC = DOC.nextSibling();
551 				continue;
552 			}
553 			int z;
554 			if (STag == "svg:polygon")
555 				z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, strokewidth, FillCol, StrokeCol);
556 			else
557 				z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, strokewidth, CommonStrings::None, StrokeCol);
558 			m_Doc->Items->at(z)->PoLine = PoLine.copy();
559 			finishItem(m_Doc->Items->at(z));
560 		}
561 		else if ((STag == "svg:circle") || (STag == "svg:ellipse"))
562 		{
563 			x1 = ScCLocale::toDoubleC(pg.attribute("r")) * Conversion;
564 			y1 = ScCLocale::toDoubleC(pg.attribute("r")) * Conversion;
565 			x2 = ScCLocale::toDoubleC(pg.attribute("cx")) * Conversion - x1;
566 			y2 = ScCLocale::toDoubleC(pg.attribute("cy")) * Conversion - y1;
567 			x1 *= 2.0;
568 			y1 *= 2.0;
569 			int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + x1, baseY + y1, x2, y2, strokewidth, FillCol, StrokeCol);
570 			m_Doc->Items->at(z)->setLineJoin(LineJoin);
571 			m_Doc->Items->at(z)->setLineEnd(LineEnd);
572 			finishItem(m_Doc->Items->at(z));
573 		}
574 		else if (STag == "svg:path")
575 		{
576 		//	poly =
577 			parseSVG( pg.attribute( "d" ), &PoLine );
578 			if (PoLine.size() < 4)
579 			{
580 				DOC = DOC.nextSibling();
581 				continue;
582 			}
583 			int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, strokewidth, FillCol, StrokeCol);
584 			m_Doc->Items->at(z)->PoLine = PoLine.copy();
585 			finishItem(m_Doc->Items->at(z));
586 		}
587 		else if (STag == "svg:g")
588 		{
589 			int z = m_Doc->itemAdd(PageItem::Group, PageItem::Rectangle, baseX, baseX, 1, 1, 0, CommonStrings::None, CommonStrings::None);
590 			PageItem *neu = m_Doc->Items->at(z);
591 			Elements.append(neu);
592 			if (groupStack.count() > 0)
593 				groupStack.top().append(neu);
594 			QList<PageItem*> gElements;
595 			groupStack.push(gElements);
596 			QDomNode child = DOC.firstChild();
597 			parseGroup(child);
598 			if (gElements.count() == 0)
599 			{
600 				groupStack.pop();
601 				Elements.removeAll(neu);
602 				groupStack.top().removeAll(neu);
603 				Selection tmpSelection(m_Doc, false);
604 				tmpSelection.addItem(neu);
605 				m_Doc->itemSelection_DeleteItem(&tmpSelection);
606 			}
607 			else
608 			{
609 				QList<PageItem*> gElem = groupStack.pop();
610 				double minx =  std::numeric_limits<double>::max();
611 				double miny =  std::numeric_limits<double>::max();
612 				double maxx = -std::numeric_limits<double>::max();
613 				double maxy = -std::numeric_limits<double>::max();
614 				for (int gr = 0; gr < gElements.count(); ++gr)
615 				{
616 					PageItem* currItem = gElem.at(gr);
617 					double x1, x2, y1, y2;
618 					currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
619 					minx = qMin(minx, x1);
620 					miny = qMin(miny, y1);
621 					maxx = qMax(maxx, x2);
622 					maxy = qMax(maxy, y2);
623 				}
624 				double gx = minx;
625 				double gy = miny;
626 				double gw = maxx - minx;
627 				double gh = maxy - miny;
628 				neu->setXYPos(gx, gy, true);
629 				neu->setWidthHeight(gw, gh, true);
630 				neu->SetRectFrame();
631 				neu->Clip = flattenPath(neu->PoLine, neu->Segments);
632 				neu->setItemName( tr("Group%1").arg(m_Doc->GroupCounter));
633 				neu->AutoName = false;
634 				neu->gXpos = neu->xPos() - gx;
635 				neu->gYpos = neu->yPos() - gy;
636 				neu->groupWidth = gw;
637 				neu->groupHeight = gh;
638 				for (int gr = 0; gr < gElem.count(); ++gr)
639 				{
640 					PageItem* currItem = gElem.at(gr);
641 					currItem->gXpos = currItem->xPos() - gx;
642 					currItem->gYpos = currItem->yPos() - gy;
643 					currItem->gWidth = gw;
644 					currItem->gHeight = gh;
645 					currItem->Parent = neu;
646 					neu->groupItemList.append(currItem);
647 					m_Doc->Items->removeAll(currItem);
648 					Elements.removeAll(currItem);
649 				}
650 				neu->setRedrawBounding();
651 				neu->setTextFlowMode(PageItem::TextFlowDisabled);
652 				m_Doc->GroupCounter++;
653 			}
654 		}
655 		DOC = DOC.nextSibling();
656 	}
657 }
658 
parseGroupProperties(QDomNode & DOC,double & minXCoor,double & minYCoor,double & maxXCoor,double & maxYCoor,bool & firstCheck)659 void ShapePlug::parseGroupProperties(QDomNode &DOC, double &minXCoor, double &minYCoor, double &maxXCoor, double &maxYCoor, bool &firstCheck)
660 {
661 	while (!DOC.isNull())
662 	{
663 		double x1, y1, x2, y2;
664 		FPointArray PoLine;
665 		PoLine.resize(0);
666 		QDomElement pg = DOC.toElement();
667 		QString STag = pg.tagName();
668 		if (STag == "svg:line")
669 		{
670 			x1 = ScCLocale::toDoubleC(pg.attribute("x1")) * Conversion;
671 			y1 = ScCLocale::toDoubleC(pg.attribute("y1")) * Conversion;
672 			x2 = ScCLocale::toDoubleC(pg.attribute("x2")) * Conversion;
673 			y2 = ScCLocale::toDoubleC(pg.attribute("y2")) * Conversion;
674 			PoLine.addPoint(x1, y1);
675 			PoLine.addPoint(x1, y1);
676 			PoLine.addPoint(x2, y2);
677 			PoLine.addPoint(x2, y2);
678 		}
679 		else if (STag == "svg:rect")
680 		{
681 			x1 = ScCLocale::toDoubleC(pg.attribute("x")) * Conversion;
682 			y1 = ScCLocale::toDoubleC(pg.attribute("y")) * Conversion;
683 			x2 = ScCLocale::toDoubleC(pg.attribute("width")) * Conversion;
684 			y2 = ScCLocale::toDoubleC(pg.attribute("height")) * Conversion;
685 			static double rect[] = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
686 									1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
687 									0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0};
688 			for (int a = 0; a < 29; a += 4)
689 			{
690 				double xa = x2 * rect[a];
691 				double ya = y2 * rect[a+1];
692 				double xb = x2 * rect[a+2];
693 				double yb = y2 * rect[a+3];
694 				PoLine.addPoint(x1+xa, y1+ya);
695 				PoLine.addPoint(x1+xb, y1+yb);
696 			}
697 		}
698 		else if ((STag == "svg:polygon") || (STag == "svg:polyline"))
699 		{
700 			bool bFirst = true;
701 			double x = 0.0;
702 			double y = 0.0;
703 			QString points = pg.attribute( "points" ).simplified().replace(',', " ");
704 			QStringList pointList = points.split(' ', Qt::SkipEmptyParts);
705 			FirstM = true;
706 			for (QStringList::Iterator it1 = pointList.begin(); it1 != pointList.end(); it1++)
707 			{
708 				x = ScCLocale::toDoubleC(*(it1++));
709 				y = ScCLocale::toDoubleC(*it1);
710 				if (bFirst)
711 				{
712 					svgMoveTo(x * Conversion, y * Conversion);
713 					bFirst = false;
714 					WasM = true;
715 				}
716 				else
717 				{
718 					svgLineTo(&PoLine, x * Conversion, y * Conversion);
719 				}
720 			}
721 			if (STag == "svg:polygon")
722 				svgClosePath(&PoLine);
723 			if (PoLine.size() < 4)
724 			{
725 				DOC = DOC.nextSibling();
726 				continue;
727 			}
728 		}
729 		else if (STag == "svg:circle")
730 		{
731 			x1 = ScCLocale::toDoubleC(pg.attribute("r")) * Conversion;
732 			y1 = ScCLocale::toDoubleC(pg.attribute("r")) * Conversion;
733 			x2 = ScCLocale::toDoubleC(pg.attribute("cx")) * Conversion - x1;
734 			y2 = ScCLocale::toDoubleC(pg.attribute("cy")) * Conversion - y1;
735 			x1 *= 2.0;
736 			y1 *= 2.0;
737 			static double rect[] = {1.0, 0.5, 1.0, 0.77615235,0.5, 1.0, 0.77615235, 1.0,
738 									0.5, 1.0, 0.22385765, 1.0, 0.0, 0.5, 0.0, 0.77615235,
739 									0.0, 0.5, 0.0, 0.22385765, 0.5, 0.0, 0.22385765, 0.0,
740 									0.5, 0.0, 0.77615235, 0.0, 1.0, 0.5, 1.0, 0.22385765};
741 			for (int a = 0; a < 29; a += 4)
742 			{
743 				double xa = x1 * rect[a];
744 				double ya = y1 * rect[a+1];
745 				double xb = x1 * rect[a+2];
746 				double yb = y1 * rect[a+3];
747 				PoLine.addPoint(x2+xa, y2+ya);
748 				PoLine.addPoint(x2+xb, y2+yb);
749 			}
750 		}
751 		else if (STag == "svg:ellipse")
752 		{
753 			x1 = ScCLocale::toDoubleC(pg.attribute("rx")) * Conversion;
754 			y1 = ScCLocale::toDoubleC(pg.attribute("ry")) * Conversion;
755 			x2 = ScCLocale::toDoubleC(pg.attribute("cx")) * Conversion - x1;
756 			y2 = ScCLocale::toDoubleC(pg.attribute("cy")) * Conversion - y1;
757 			x1 *= 2.0;
758 			y1 *= 2.0;
759 			static double rect[] = {1.0, 0.5, 1.0, 0.77615235,0.5, 1.0, 0.77615235, 1.0,
760 									0.5, 1.0, 0.22385765, 1.0, 0.0, 0.5, 0.0, 0.77615235,
761 									0.0, 0.5, 0.0, 0.22385765, 0.5, 0.0, 0.22385765, 0.0,
762 									0.5, 0.0, 0.77615235, 0.0, 1.0, 0.5, 1.0, 0.22385765};
763 			for (int a = 0; a < 29; a += 4)
764 			{
765 				double xa = x1 * rect[a];
766 				double ya = y1 * rect[a+1];
767 				double xb = x1 * rect[a+2];
768 				double yb = y1 * rect[a+3];
769 				PoLine.addPoint(x2+xa, y2+ya);
770 				PoLine.addPoint(x2+xb, y2+yb);
771 			}
772 		}
773 		else if (STag == "svg:path")
774 		{
775 			parseSVG( pg.attribute( "d" ), &PoLine );
776 			if (PoLine.size() < 4)
777 			{
778 				DOC = DOC.nextSibling();
779 				continue;
780 			}
781 		}
782 		else if (STag == "svg:g")
783 		{
784 			QDomNode child = DOC.firstChild();
785 			parseGroupProperties(child, minXCoor, minYCoor, maxXCoor, maxYCoor, firstCheck);
786 		}
787 		if (PoLine.size() < 4)
788 		{
789 			DOC = DOC.nextSibling();
790 			continue;
791 		}
792 		FPoint tp2(getMinClipF(&PoLine));
793 		PoLine.translate(-tp2.x(), -tp2.y());
794 		FPoint wh(getMaxClipF(&PoLine));
795 		if (firstCheck)
796 		{
797 			minXCoor = tp2.x();
798 			minYCoor = tp2.y();
799 			maxXCoor = tp2.x() + wh.x();
800 			maxYCoor = tp2.y() + wh.y();
801 			firstCheck = false;
802 		}
803 		else
804 		{
805 			minXCoor = qMin(minXCoor, tp2.x());
806 			minYCoor = qMin(minYCoor, tp2.y());
807 			maxXCoor = qMax(maxXCoor, tp2.x() + wh.x());
808 			maxYCoor = qMax(maxYCoor, tp2.y() + wh.y());
809 		}
810 		DOC = DOC.nextSibling();
811 	}
812 }
813 
parseUnit(const QString & unit)814 double ShapePlug::parseUnit(const QString &unit)
815 {
816 	QString sCM(unitGetUntranslatedStrFromIndex(SC_CM));
817 	QString sMM(unitGetUntranslatedStrFromIndex(SC_MM));
818 	QString sIN(unitGetUntranslatedStrFromIndex(SC_IN));
819 	QString sPT(unitGetUntranslatedStrFromIndex(SC_PT));
820 	QString sPX("px");
821 
822 	bool noUnit = false;
823 	QString unitval(unit);
824 	if (unit.right( 2 ) == sPT)
825 		unitval.replace( sPT, "" );
826 	else if (unit.right( 2 ) == sCM)
827 		unitval.replace( sCM, "" );
828 	else if (unit.right( 2 ) == sMM)
829 		unitval.replace( sMM , "" );
830 	else if (unit.right( 2 ) == sIN)
831 		unitval.replace( sIN, "" );
832 	else if (unit.right( 2 ) == sPX)
833 		unitval.replace( sPX, "" );
834 	if (unitval == unit)
835 		noUnit = true;
836 	double value = ScCLocale::toDoubleC(unitval);
837 	if (unit.right( 2 ) == sPT)
838 		{}/* value = value; */ //no change
839 	else if (unit.right( 2 ) == sCM)
840 	{
841 		value = cm2pts(value);
842 		Conversion = 1/unitGetRatioFromIndex(SC_CM);
843 	}
844 	else if (unit.right( 2 ) == sMM)
845 	{
846 		value = mm2pts(value);
847 		Conversion = 1/unitGetRatioFromIndex(SC_MM);
848 	}
849 	else if (unit.right( 2 ) == sIN)
850 	{
851 		value = in2pts(value);
852 		Conversion = 1/unitGetRatioFromIndex(SC_IN);
853 	}
854 	else if (unit.right( 2 ) == sPX)
855 	{
856 		value = value * 0.8;
857 		Conversion = 0.8;
858 	}
859 	else if (noUnit)
860 		{}/* value = value; */ //no change
861 	return value;
862 }
863 
getCoord(const char * ptr,double & number)864 const char * ShapePlug::getCoord( const char *ptr, double &number )
865 {
866 	int integer, exponent;
867 	double decimal, frac;
868 	int sign, expsign;
869 
870 	exponent = 0;
871 	integer = 0;
872 	frac = 1.0;
873 	decimal = 0;
874 	sign = 1;
875 	expsign = 1;
876 
877 	// read the sign
878 	if (*ptr == '+')
879 		ptr++;
880 	else if (*ptr == '-')
881 	{
882 		ptr++;
883 		sign = -1;
884 	}
885 
886 	// read the integer part
887 	while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
888 		integer = (integer * 10) + *(ptr++) - '0';
889 	if (*ptr == '.') // read the decimals
890 	{
891 		ptr++;
892 		while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
893 			decimal += (*(ptr++) - '0') * (frac *= 0.1);
894 	}
895 
896 	if (*ptr == 'e' || *ptr == 'E') // read the exponent part
897 	{
898 		ptr++;
899 
900 		// read the sign of the exponent
901 		if (*ptr == '+')
902 			ptr++;
903 		else if (*ptr == '-')
904 		{
905 			ptr++;
906 			expsign = -1;
907 		}
908 
909 		exponent = 0;
910 		while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
911 		{
912 			exponent *= 10;
913 			exponent += *ptr - '0';
914 			ptr++;
915 		}
916 	}
917 	number = integer + decimal;
918 	number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
919 	// skip the following space
920 	if (*ptr == ' ')
921 		ptr++;
922 
923 	return ptr;
924 }
925 
parseSVG(const QString & s,FPointArray * ite)926 bool ShapePlug::parseSVG( const QString &s, FPointArray *ite )
927 {
928 	QString d = s;
929 	d = d.replace( QRegExp( "," ), " ");
930 	bool ret = false;
931 	if (!d.isEmpty())
932 	{
933 		d = d.simplified();
934 		QByteArray pathData = d.toLatin1();
935 		const char *ptr = pathData.constData();
936 		const char *end = pathData.constData() + pathData.length() + 1;
937 		double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
938 		double px1, py1, px2, py2, px3, py3;
939 		bool relative;
940 		FirstM = true;
941 		char command = *(ptr++), lastCommand = ' ';
942 		subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
943 		while (ptr < end)
944 		{
945 			if (*ptr == ' ')
946 				ptr++;
947 			relative = false;
948 			switch (command)
949 			{
950 			case 'm':
951 				relative = true;
952 			case 'M':
953 				{
954 					ptr = getCoord( ptr, tox );
955 					ptr = getCoord( ptr, toy );
956 					tox *= Conversion;
957 					toy *= Conversion;
958 					WasM = true;
959 					subpathx = curx = relative ? curx + tox : tox;
960 					subpathy = cury = relative ? cury + toy : toy;
961 					svgMoveTo(curx, cury );
962 					break;
963 				}
964 			case 'l':
965 				relative = true;
966 			case 'L':
967 				{
968 					ptr = getCoord( ptr, tox );
969 					ptr = getCoord( ptr, toy );
970 					tox *= Conversion;
971 					toy *= Conversion;
972 					curx = relative ? curx + tox : tox;
973 					cury = relative ? cury + toy : toy;
974 					svgLineTo(ite, curx, cury );
975 					break;
976 				}
977 			case 'h':
978 				{
979 					ptr = getCoord( ptr, tox );
980 					tox *= Conversion;
981 					curx = curx + tox;
982 					svgLineTo(ite, curx, cury );
983 					break;
984 				}
985 			case 'H':
986 				{
987 					ptr = getCoord( ptr, tox );
988 					tox *= Conversion;
989 					curx = tox;
990 					svgLineTo(ite, curx, cury );
991 					break;
992 				}
993 			case 'v':
994 				{
995 					ptr = getCoord( ptr, toy );
996 					toy *= Conversion;
997 					cury = cury + toy;
998 					svgLineTo(ite, curx, cury );
999 					break;
1000 				}
1001 			case 'V':
1002 				{
1003 					ptr = getCoord( ptr, toy );
1004 					toy *= Conversion;
1005 					cury = toy;
1006 					svgLineTo(ite,  curx, cury );
1007 					break;
1008 				}
1009 			case 'z':
1010 			case 'Z':
1011 				{
1012 					curx = subpathx;
1013 					cury = subpathy;
1014 					svgClosePath(ite);
1015 					break;
1016 				}
1017 			case 'c':
1018 				relative = true;
1019 			case 'C':
1020 				{
1021 					ptr = getCoord( ptr, x1 );
1022 					ptr = getCoord( ptr, y1 );
1023 					ptr = getCoord( ptr, x2 );
1024 					ptr = getCoord( ptr, y2 );
1025 					ptr = getCoord( ptr, tox );
1026 					ptr = getCoord( ptr, toy );
1027 					tox *= Conversion;
1028 					toy *= Conversion;
1029 					x1 *= Conversion;
1030 					y1 *= Conversion;
1031 					x2 *= Conversion;
1032 					y2 *= Conversion;
1033 					px1 = relative ? curx + x1 : x1;
1034 					py1 = relative ? cury + y1 : y1;
1035 					px2 = relative ? curx + x2 : x2;
1036 					py2 = relative ? cury + y2 : y2;
1037 					px3 = relative ? curx + tox : tox;
1038 					py3 = relative ? cury + toy : toy;
1039 					svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1040 					contrlx = relative ? curx + x2 : x2;
1041 					contrly = relative ? cury + y2 : y2;
1042 					curx = relative ? curx + tox : tox;
1043 					cury = relative ? cury + toy : toy;
1044 					break;
1045 				}
1046 			case 's':
1047 				relative = true;
1048 			case 'S':
1049 				{
1050 					ptr = getCoord( ptr, x2 );
1051 					ptr = getCoord( ptr, y2 );
1052 					ptr = getCoord( ptr, tox );
1053 					ptr = getCoord( ptr, toy );
1054 					tox *= Conversion;
1055 					toy *= Conversion;
1056 					x2 *= Conversion;
1057 					y2 *= Conversion;
1058 					px1 = 2 * curx - contrlx;
1059 					py1 = 2 * cury - contrly;
1060 					px2 = relative ? curx + x2 : x2;
1061 					py2 = relative ? cury + y2 : y2;
1062 					px3 = relative ? curx + tox : tox;
1063 					py3 = relative ? cury + toy : toy;
1064 					svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1065 					contrlx = relative ? curx + x2 : x2;
1066 					contrly = relative ? cury + y2 : y2;
1067 					curx = relative ? curx + tox : tox;
1068 					cury = relative ? cury + toy : toy;
1069 					break;
1070 				}
1071 			case 'q':
1072 				relative = true;
1073 			case 'Q':
1074 				{
1075 					ptr = getCoord( ptr, x1 );
1076 					ptr = getCoord( ptr, y1 );
1077 					ptr = getCoord( ptr, tox );
1078 					ptr = getCoord( ptr, toy );
1079 					tox *= Conversion;
1080 					toy *= Conversion;
1081 					x1 *= Conversion;
1082 					y1 *= Conversion;
1083 					px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
1084 					py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
1085 					px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
1086 					py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
1087 					px3 = relative ? curx + tox : tox;
1088 					py3 = relative ? cury + toy : toy;
1089 					svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1090 					contrlx = relative ? curx + x1 : (tox + 2 * x1) * (1.0 / 3.0);
1091 					contrly = relative ? cury + y1 : (toy + 2 * y1) * (1.0 / 3.0);
1092 					curx = relative ? curx + tox : tox;
1093 					cury = relative ? cury + toy : toy;
1094 					break;
1095 				}
1096 			case 't':
1097 				relative = true;
1098 			case 'T':
1099 				{
1100 					ptr = getCoord(ptr, tox);
1101 					ptr = getCoord(ptr, toy);
1102 					tox *= Conversion;
1103 					toy *= Conversion;
1104 					xc = 2 * curx - contrlx;
1105 					yc = 2 * cury - contrly;
1106 					px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
1107 					py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
1108 					px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
1109 					py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
1110 					px3 = relative ? curx + tox : tox;
1111 					py3 = relative ? cury + toy : toy;
1112 					svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1113 					contrlx = xc;
1114 					contrly = yc;
1115 					curx = relative ? curx + tox : tox;
1116 					cury = relative ? cury + toy : toy;
1117 					break;
1118 				}
1119 			}
1120 			lastCommand = command;
1121 			if (*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
1122 			{
1123 				// there are still coords in this command
1124 				if (command == 'M')
1125 					command = 'L';
1126 				else if (command == 'm')
1127 					command = 'l';
1128 			}
1129 			else
1130 				command = *(ptr++);
1131 
1132 			if (lastCommand != 'C' && lastCommand != 'c' &&
1133 			        lastCommand != 'S' && lastCommand != 's' &&
1134 			        lastCommand != 'Q' && lastCommand != 'q' &&
1135 			        lastCommand != 'T' && lastCommand != 't')
1136 			{
1137 				contrlx = curx;
1138 				contrly = cury;
1139 			}
1140 		}
1141 		if ((lastCommand != 'z') && (lastCommand != 'Z'))
1142 			ret = true;
1143 		if (ite->size() > 2)
1144 		{
1145 			if ((ite->point(0).x() == ite->point(ite->size()-2).x()) && (ite->point(0).y() == ite->point(ite->size()-2).y()))
1146 				ret = false;
1147 		}
1148 	}
1149 	return ret;
1150 }
1151 
svgMoveTo(double x1,double y1)1152 void ShapePlug::svgMoveTo(double x1, double y1)
1153 {
1154 	CurrX = x1;
1155 	CurrY = y1;
1156 	StartX = x1;
1157 	StartY = y1;
1158 	PathLen = 0;
1159 }
1160 
svgLineTo(FPointArray * i,double x1,double y1)1161 void ShapePlug::svgLineTo(FPointArray *i, double x1, double y1)
1162 {
1163 	if ((!FirstM) && (WasM))
1164 	{
1165 		i->setMarker();
1166 		PathLen += 4;
1167 	}
1168 	FirstM = false;
1169 	WasM = false;
1170 	if (i->size() > 3)
1171 	{
1172 		const FPoint& b1 = i->point(i->size()-4);
1173 		const FPoint& b2 = i->point(i->size()-3);
1174 		const FPoint& b3 = i->point(i->size()-2);
1175 		const FPoint& b4 = i->point(i->size()-1);
1176 		FPoint n1 = FPoint(CurrX, CurrY);
1177 		FPoint n2 = FPoint(x1, y1);
1178 		if ((b1 == n1) && (b2 == n1) && (b3 == n2) && (b4 == n2))
1179 			return;
1180 	}
1181 	i->addPoint(FPoint(CurrX, CurrY));
1182 	i->addPoint(FPoint(CurrX, CurrY));
1183 	i->addPoint(FPoint(x1, y1));
1184 	i->addPoint(FPoint(x1, y1));
1185 	CurrX = x1;
1186 	CurrY = y1;
1187 	PathLen += 4;
1188 }
1189 
svgCurveToCubic(FPointArray * i,double x1,double y1,double x2,double y2,double x3,double y3)1190 void ShapePlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3)
1191 {
1192 	if ((!FirstM) && (WasM))
1193 	{
1194 		i->setMarker();
1195 		PathLen += 4;
1196 	}
1197 	FirstM = false;
1198 	WasM = false;
1199 	if (PathLen > 3)
1200 	{
1201 		const FPoint& b1 = i->point(i->size()-4);
1202 		const FPoint& b2 = i->point(i->size()-3);
1203 		const FPoint& b3 = i->point(i->size()-2);
1204 		const FPoint& b4 = i->point(i->size()-1);
1205 		FPoint n1 = FPoint(CurrX, CurrY);
1206 		FPoint n2 = FPoint(x1, y1);
1207 		FPoint n3 = FPoint(x3, y3);
1208 		FPoint n4 = FPoint(x2, y2);
1209 		if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4))
1210 			return;
1211 	}
1212 	i->addPoint(FPoint(CurrX, CurrY));
1213 	i->addPoint(FPoint(x1, y1));
1214 	i->addPoint(FPoint(x3, y3));
1215 	i->addPoint(FPoint(x2, y2));
1216 	CurrX = x3;
1217 	CurrY = y3;
1218 	PathLen += 4;
1219 }
1220 
svgClosePath(FPointArray * i)1221 void ShapePlug::svgClosePath(FPointArray *i)
1222 {
1223 	if (PathLen > 2)
1224 	{
1225 		if ((PathLen == 4) || (i->point(i->size()-2).x() != StartX) || (i->point(i->size()-2).y() != StartY))
1226 		{
1227 			i->addPoint(i->point(i->size()-2));
1228 			i->addPoint(i->point(i->size()-3));
1229 			i->addPoint(FPoint(StartX, StartY));
1230 			i->addPoint(FPoint(StartX, StartY));
1231 		}
1232 	}
1233 }
1234