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                           importcgm.cpp  -  description
9                              -------------------
10     begin                : Wed Dez 23 2009
11     copyright            : (C) 2009 by Franz Schmid
12     email                : Franz.Schmid@altmuehlnet.de
13  ***************************************************************************/
14 
15 #include <QByteArray>
16 #include <QCursor>
17 #include <QDrag>
18 #include <QFile>
19 #include <QList>
20 #include <QMimeData>
21 #include <QRegExp>
22 #include <QStack>
23 #include <QDebug>
24 
25 #include <cstdlib>
26 
27 
28 #include "commonstrings.h"
29 #include "importcgm.h"
30 #include "loadsaveplugin.h"
31 #include "pagesize.h"
32 #include "prefscontext.h"
33 #include "prefsfile.h"
34 #include "prefsmanager.h"
35 #include "prefstable.h"
36 #include "rawimage.h"
37 #include "scclocale.h"
38 #include "sccolorengine.h"
39 #include "scconfig.h"
40 #include "scmimedata.h"
41 #include "scpaths.h"
42 #include "scribusXml.h"
43 #include "scribuscore.h"
44 #include "scribusview.h"
45 #include "sctextstream.h"
46 #include "selection.h"
47 #include "ui/customfdialog.h"
48 #include "ui/missing.h"
49 #include "ui/multiprogressdialog.h"
50 #include "ui/propertiespalette.h"
51 #include "undomanager.h"
52 #include "util.h"
53 #include "util_formats.h"
54 #include "util_math.h"
55 
ScBitReader(QByteArray & data)56 ScBitReader::ScBitReader(QByteArray &data)
57 {
58 	buffer = data;
59 	actBit = 7;
60 	actByte = 0;
61 }
62 
~ScBitReader()63 ScBitReader::~ScBitReader()
64 {
65 }
66 
getUInt(uint size)67 quint32 ScBitReader::getUInt(uint size)
68 {
69 	quint32 ret = 0;
70 	if (size > 32)
71 		return 0;
72 	quint8 dat = buffer[actByte];
73 	for (uint c = 0; c < size; c++)
74 	{
75 		ret = (ret << 1) | ((dat & (0x01 << actBit)) >> actBit);
76 		actBit--;
77 		if (actBit < 0)
78 		{
79 			actBit = 7;
80 			actByte++;
81 			if (actByte >= buffer.count())
82 				break;
83 			dat = buffer[actByte];
84 		}
85 	}
86 	return ret;
87 }
88 
alignToWord()89 void ScBitReader::alignToWord()
90 {
91 	if (actByte < buffer.count() - 1)
92 	{
93 		actByte++;
94 		actByte += actByte % 2;
95 		actBit = 7;
96 	}
97 }
98 
CgmPlug(ScribusDoc * doc,int flags)99 CgmPlug::CgmPlug(ScribusDoc* doc, int flags)
100 {
101 	tmpSel = new Selection(this, false);
102 	m_Doc = doc;
103 	importerFlags = flags;
104 	interactive = (flags & LoadSavePlugin::lfInteractive);
105 	progressDialog = nullptr;
106 }
107 
readThumbnail(const QString & fName)108 QImage CgmPlug::readThumbnail(const QString& fName)
109 {
110 	QFileInfo fi = QFileInfo(fName);
111 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
112 	double b, h;
113 	b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
114 	h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
115 	docWidth = b;
116 	docHeight = h;
117 	progressDialog = nullptr;
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 QImage();
164 }
165 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)166 bool CgmPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
167 {
168 	bool success = false;
169 	interactive = (flags & LoadSavePlugin::lfInteractive);
170 	importerFlags = flags;
171 	cancel = false;
172 	double b, h;
173 	bool ret = false;
174 	CustColors.clear();
175 	QFileInfo fi = QFileInfo(fNameIn);
176 	if (!ScCore->usingGUI())
177 	{
178 		interactive = false;
179 		showProgress = false;
180 	}
181 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
182 	if (showProgress)
183 	{
184 		ScribusMainWindow* mw = (m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
185 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
186 		QStringList barNames, barTexts;
187 		barNames << "GI";
188 		barTexts << tr("Analyzing File:");
189 		QList<bool> barsNumeric;
190 		barsNumeric << false;
191 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
192 		progressDialog->setOverallTotalSteps(3);
193 		progressDialog->setOverallProgress(0);
194 		progressDialog->setProgress("GI", 0);
195 		progressDialog->show();
196 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
197 		qApp->processEvents();
198 	}
199 	else
200 		progressDialog = nullptr;
201 /* Set default Page to size defined in Preferences */
202 	b = 0.0;
203 	h = 0.0;
204 	if (progressDialog)
205 	{
206 		progressDialog->setOverallProgress(1);
207 		qApp->processEvents();
208 	}
209 	b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
210 	h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
211 	docWidth = b;
212 	docHeight = h;
213 	baseX = 0;
214 	baseY = 0;
215 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
216 	{
217 		m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
218 		m_Doc->addPage(0);
219 		m_Doc->view()->addPage(0, true);
220 		baseX = 0;
221 		baseY = 0;
222 	}
223 	else
224 	{
225 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
226 		{
227 			m_Doc = ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
228 			ScCore->primaryMainWindow()->HaveNewDoc();
229 			ret = true;
230 			baseX = 0;
231 			baseY = 0;
232 			baseX = m_Doc->currentPage()->xOffset();
233 			baseY = m_Doc->currentPage()->yOffset();
234 		}
235 	}
236 	if ((!ret) && (interactive))
237 	{
238 		baseX = m_Doc->currentPage()->xOffset();
239 		baseY = m_Doc->currentPage()->yOffset();
240 	}
241 	if ((ret) || (!interactive))
242 	{
243 		if (docWidth > docHeight)
244 			m_Doc->setPageOrientation(1);
245 		else
246 			m_Doc->setPageOrientation(0);
247 		m_Doc->setPageSize("Custom");
248 	}
249 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
250 		m_Doc->view()->deselectItems();
251 	Elements.clear();
252 	m_Doc->setLoading(true);
253 	m_Doc->DoDrawing = false;
254 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
255 		m_Doc->view()->updatesOn(false);
256 	m_Doc->scMW()->setScriptRunning(true);
257 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
258 	QString CurDirP = QDir::currentPath();
259 	QDir::setCurrent(fi.path());
260 	if (convert(fNameIn))
261 	{
262 		tmpSel->clear();
263 		QDir::setCurrent(CurDirP);
264 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
265 		{
266 			PageItem* group = m_Doc->groupObjectsList(Elements);
267 			if (!pictName.isEmpty())
268 				group->setItemName(group->generateUniqueCopyName(pictName, false).replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%\\.]"), "_" ));
269 		}
270 		m_Doc->DoDrawing = true;
271 		m_Doc->scMW()->setScriptRunning(false);
272 		m_Doc->setLoading(false);
273 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
274 		if ((Elements.count() > 0) && (!ret) && (interactive))
275 		{
276 			if (flags & LoadSavePlugin::lfScripted)
277 			{
278 				bool loadF = m_Doc->isLoading();
279 				m_Doc->setLoading(false);
280 				m_Doc->changed();
281 				m_Doc->setLoading(loadF);
282 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
283 				{
284 					m_Doc->m_Selection->delaySignalsOn();
285 					for (int dre = 0; dre < Elements.count(); ++dre)
286 					{
287 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
288 					}
289 					m_Doc->m_Selection->delaySignalsOff();
290 					m_Doc->m_Selection->setGroupRect();
291 					if (m_Doc->view() != nullptr)
292 						m_Doc->view()->updatesOn(true);
293 				}
294 			}
295 			else
296 			{
297 				m_Doc->DragP = true;
298 				m_Doc->DraggedElem = nullptr;
299 				m_Doc->DragElements.clear();
300 				m_Doc->m_Selection->delaySignalsOn();
301 				for (int dre = 0; dre < Elements.count(); ++dre)
302 				{
303 					tmpSel->addItem(Elements.at(dre), true);
304 				}
305 				tmpSel->setGroupRect();
306 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
307 				m_Doc->itemSelection_DeleteItem(tmpSel);
308 				m_Doc->view()->updatesOn(true);
309 				m_Doc->m_Selection->delaySignalsOff();
310 				// We must copy the TransationSettings object as it is owned
311 				// by handleObjectImport method afterwards
312 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
313 				m_Doc->view()->handleObjectImport(md, transacSettings);
314 				m_Doc->DragP = false;
315 				m_Doc->DraggedElem = nullptr;
316 				m_Doc->DragElements.clear();
317 			}
318 		}
319 		else
320 		{
321 			m_Doc->changed();
322 			m_Doc->reformPages();
323 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
324 				m_Doc->view()->updatesOn(true);
325 		}
326 		success = true;
327 	}
328 	else
329 	{
330 		QDir::setCurrent(CurDirP);
331 		m_Doc->DoDrawing = true;
332 		m_Doc->scMW()->setScriptRunning(false);
333 		m_Doc->view()->updatesOn(true);
334 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
335 	}
336 	if (interactive)
337 		m_Doc->setLoading(false);
338 	//CB If we have a gui we must refresh it if we have used the progressbar
339 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
340 	{
341 		if ((showProgress) && (!interactive))
342 			m_Doc->view()->DrawNew();
343 	}
344 	qApp->restoreOverrideCursor();
345 	return success;
346 }
347 
~CgmPlug()348 CgmPlug::~CgmPlug()
349 {
350 	delete progressDialog;
351 	delete tmpSel;
352 }
353 
parseHeader(const QString & fName,double & b,double & h)354 void CgmPlug::parseHeader(const QString& fName, double &b, double &h)
355 {
356 }
357 
convert(const QString & fn)358 bool CgmPlug::convert(const QString& fn)
359 {
360 	Coords.resize(0);
361 	Coords.svgInit();
362 	importedColors.clear();
363 	QList<PageItem*> gElements;
364 	groupStack.push(gElements);
365 	currentItemNr = 0;
366 	importRunning = true;
367 	firstPage = true;
368 	vcdSet = false;
369 	metaFileVersion = 1;
370 	vdcType = 0;
371 	vdcInt = 16;
372 	vdcReal = 1;
373 	vdcMantissa = 16;
374 	vcdFlippedH = false;
375 	vcdFlippedV = true;
376 	intPrecision = 16;
377 	realPrecision = 1;
378 	realMantissa = 16;
379 	realFraction = 16;
380 	realPrecisionSet = false;
381 	indexPrecision = 16;
382 	colorPrecision = 8;
383 	colorIndexPrecision = 8;
384 	maxColorIndex = 63;
385 	m_colorModel = 1;
386 	colorMode = 0;
387 	namePrecision = 16;
388 	metaFileScaleMode = 0;
389 	metaFileScale = 1.0;
390 	metaScale = 400.0 / 32768.0;
391 	lineWidthMode = 1;
392 	edgeWidthMode = 1;
393 	markerSizeMode = 1;
394 	viewPortScale = 1.0;
395 	viewPortScaleMode = 0;
396 	lineType = Qt::SolidLine;
397 	lineCap = Qt::FlatCap;
398 	lineJoin = Qt::MiterJoin;
399 	lineWidth = 1.0;
400 	lineColor = "Black";
401 	edgeType = Qt::SolidLine;
402 	edgeCap = Qt::FlatCap;
403 	edgeJoin = Qt::MiterJoin;
404 	edgeWidth = 0.0;
405 	edgeColor = "Black";
406 	fillColor = "Black";
407 	backgroundColor = "White";
408 	patternIndex = 1;
409 	patternTable.clear();
410 	patternScaleX = -1;
411 	patternScaleY = -1;
412 	backgroundSet = false;
413 	fillType = 1;
414 	minColor = 0;
415 	maxColor = 255;
416 	clipRect = QRectF();
417 	useClipRect = true;
418 	clipSet = false;
419 	lineVisible = true;
420 	recordRegion = false;
421 	wasEndPic = false;
422 	recordFigure = false;
423 	fontID_Map.clear();
424 	m_fontIndex = 1;
425 	textSize = 12;
426 	textColor = "Black";
427 	textAlignH = 0;
428 	textScaleMode = 1;
429 	currentRegion = 0;
430 	pictName = "";
431 	if (progressDialog)
432 	{
433 		progressDialog->setOverallProgress(2);
434 		progressDialog->setLabel("GI", tr("Generating Items"));
435 		qApp->processEvents();
436 	}
437 	QFile f(fn);
438 	if (f.open(QIODevice::ReadOnly))
439 	{
440 		oldDocItemCount = m_Doc->Items->count();
441 		int fSize = (int) f.size();
442 		if (progressDialog)
443 		{
444 			progressDialog->setTotalSteps("GI", fSize);
445 			qApp->processEvents();
446 		}
447 		QDataStream ts(&f);
448 		ts.setByteOrder(QDataStream::BigEndian);
449 		quint32 magic;
450 		ts >> magic;
451 		ts.device()->seek(0);
452 		if (magic == 0x4265674D)
453 			decodeText(f);
454 		else
455 		{
456 			while (!ts.atEnd() && (importRunning))
457 			{
458 				quint16 data, elemClass, elemID, paramLen;
459 				ts >> data;
460 				elemClass = (data & 0xF000) >> 12;
461 				elemID    = (data & 0x0FE0) >>  5;
462 				paramLen  = data & 0x001F;
463 				if (paramLen == 31)
464 					ts >> paramLen;
465 			//	qDebug() << "CGM Command Class" << elemClass << "ID" << elemID << "ParamLen" << paramLen;
466 				decodeBinary(ts, elemClass, elemID, paramLen);
467 				if (progressDialog)
468 				{
469 					progressDialog->setProgress("GI", ts.device()->pos());
470 					qApp->processEvents();
471 				}
472 			}
473 		}
474 		f.close();
475 		if (Elements.count() == 0)
476 		{
477 			if (importedColors.count() != 0)
478 			{
479 				for (int cd = 0; cd < importedColors.count(); cd++)
480 				{
481 					m_Doc->PageColors.remove(importedColors[cd]);
482 				}
483 			}
484 		}
485 		else
486 		{
487 			if (backgroundSet)
488 			{
489 				tmpSel->clear();
490 				tmpSel->delaySignalsOn();
491 				for (int dre = 0; dre < Elements.count(); ++dre)
492 				{
493 					tmpSel->addItem(Elements.at(dre), true);
494 				}
495 				tmpSel->setGroupRect();
496 				double gx, gy, gw, gh;
497 				tmpSel->getVisualGroupRect(&gx, &gy, &gw, &gh);
498 				tmpSel->clear();
499 				tmpSel->delaySignalsOff();
500 				int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, backgroundColor, CommonStrings::None);
501 				PageItem *ite = m_Doc->Items->takeAt(z);
502 				Elements.prepend(ite);
503 				m_Doc->Items->insert(oldDocItemCount, ite);
504 			}
505 		}
506 	}
507 	if (progressDialog)
508 		progressDialog->close();
509 	return true;
510 }
511 
decodeText(QFile & f)512 void CgmPlug::decodeText(QFile &f)
513 {
514 	qDebug() << "Parsing Text Data not supported yet";
515 }
516 
517 /* Start binary Decoder */
decodeBinary(QDataStream & ts,quint16 elemClass,quint16 elemID,quint16 paramLen)518 void CgmPlug::decodeBinary(QDataStream &ts, quint16 elemClass, quint16 elemID, quint16 paramLen)
519 {
520 	qint64 pos = ts.device()->pos();
521 	if (elemClass == 0)
522 		decodeClass0(ts, elemID, paramLen);
523 	else if (elemClass == 1)
524 		decodeClass1(ts, elemID, paramLen);
525 	else if (elemClass == 2)
526 		decodeClass2(ts, elemID, paramLen);
527 	else if (elemClass == 3)
528 		decodeClass3(ts, elemID, paramLen);
529 	else if (elemClass == 4)
530 		decodeClass4(ts, elemID, paramLen);
531 	else if (elemClass == 5)
532 		decodeClass5(ts, elemID, paramLen);
533 	else if (elemClass == 6)
534 		decodeClass6(ts, elemID, paramLen);
535 	else if (elemClass == 7)
536 		decodeClass7(ts, elemID, paramLen);
537 	else if (elemClass == 8)
538 		decodeClass8(ts, elemID, paramLen);
539 	else if (elemClass == 9)
540 		decodeClass9(ts, elemID, paramLen);
541 	else
542 	{
543 		importRunning = false;
544 		qDebug() << "Class" << elemClass << "ID" << elemID << "Len" << paramLen << "at" << ts.device()->pos();
545 	}
546 	ts.device()->seek(pos);
547 	alignStreamToWord(ts, paramLen);
548 	alignStreamToWord(ts, 0);
549 }
550 
decodeClass0(QDataStream & ts,quint16 elemID,quint16 paramLen)551 void CgmPlug::decodeClass0(QDataStream &ts, quint16 elemID, quint16 paramLen)
552 {
553 	if (elemID == 0)
554 	{
555 		qDebug() << "NO OP";
556 	}
557 	else if (elemID == 1)
558 		handleStartMetaFile(getBinaryText(ts));
559 	else if (elemID == 2)
560 	{
561 		importRunning = false;
562 		// qDebug() << "END METAFILE";
563 	}
564 	else if (elemID == 3)
565 		handleStartPicture(getBinaryText(ts));
566 	else if (elemID == 4)
567 	{
568 		if (vcdSet)
569 		{
570 			double w = vdcWidth * metaScale;
571 			double h = vdcHeight * metaScale;
572 			handleStartPictureBody(w, h);
573 		}
574 		else
575 		{
576 			handleStartPictureBody(docWidth, docHeight);
577 			firstPage = true;
578 		}
579 	//	qDebug() << "BEGIN PICTURE BODY";
580 	}
581 	else if (elemID == 5)
582 	{
583 		if (vcdSet)
584 		{
585 			if (firstPage)
586 			{
587 				double w = vdcWidth * metaScale;
588 				double h = vdcHeight * metaScale;
589 				handleStartPictureBody(w, h);
590 			}
591 		}
592 		else
593 		{
594 			if (firstPage)
595 				handleStartPictureBody(docWidth, docHeight);
596 		}
597 		wasEndPic = true;
598 	//	qDebug() << "END PICTURE";
599 	}
600 	else if (elemID == 6)
601 	{
602 		qDebug() << "BEGIN SEGMENT";
603 	}
604 	else if (elemID == 7)
605 	{
606 		qDebug() << "END SEGMENT";
607 	}
608 	else if (elemID == 8)
609 	{
610 		recordFigure = true;
611 		figurePath = QPainterPath();
612 		figClose = false;
613 		figDocIndex = m_Doc->Items->count();
614 		figElemIndex = Elements.count();
615 		figGstIndex = 0;
616 		figFillColor = fillColor;
617 		if (groupStack.count() != 0)
618 			figGstIndex = groupStack.top().count();
619 	//	qDebug() << "BEGIN FIGURE";
620 	}
621 	else if (elemID == 9)
622 	{
623 		recordFigure = false;
624 		if (!figurePath.isEmpty())
625 		{
626 			figurePath.closeSubpath();
627 			Coords.fromQPainterPath(figurePath);
628 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, figFillColor, CommonStrings::None);
629 			ite->PoLine = Coords.copy();
630 			ite->ClipEdited = true;
631 			ite->FrameType = 3;
632 			FPoint wh = getMaxClipF(&ite->PoLine);
633 			ite->setWidthHeight(wh.x(),wh.y());
634 			ite->setTextFlowMode(PageItem::TextFlowDisabled);
635 			m_Doc->adjustItemSize(ite);
636 			ite->OldB2 = ite->width();
637 			ite->OldH2 = ite->height();
638 			ite->updateClip();
639 			m_Doc->Items->takeLast();
640 			m_Doc->Items->insert(figDocIndex, ite);
641 			Elements.insert(figElemIndex, ite);
642 			if (groupStack.count() != 0)
643 				groupStack.top().insert(figGstIndex, ite);
644 		}
645 		figurePath = QPainterPath();
646 	//	qDebug() << "END FIGURE";
647 	}
648 	else if (elemID == 13)
649 	{
650 		uint type = getBinaryUInt(ts, indexPrecision);
651 		currentRegion = type;
652 		recordRegion = true;
653 		regionPath = QPainterPath();
654 		// qDebug() << "BEGIN PROTECTION REGION" << type;
655 	}
656 	else if (elemID == 14)
657 	{
658 		recordRegion = false;
659 		regionMap.insert(currentRegion, regionPath);
660 		// qDebug() << "END PROTECTION REGION";
661 	}
662 	else if (elemID == 15)
663 	{
664 		qDebug() << "BEGIN COMPOUND LINE";
665 	}
666 	else if (elemID == 16)
667 	{
668 		qDebug() << "END COMPOUND LINE";
669 	}
670 	else if (elemID == 17)
671 	{
672 		qDebug() << "BEGIN COMPOUND TEXT PATH";
673 	}
674 	else if (elemID == 18)
675 	{
676 		qDebug() << "END COMPOUND TEXT PATH";
677 	}
678 	else if (elemID == 19)
679 	{
680 		qDebug() << "BEGIN TILE ARRAY";
681 	}
682 	else if (elemID == 20)
683 	{
684 		qDebug() << "END TILE ARRAY";
685 	}
686 	else if (elemID == 21)
687 	{
688 		qDebug() << "BEGIN APPLICATION STRUCTURE";
689 	}
690 	else if (elemID == 22)
691 	{
692 		qDebug() << "BEGIN APPLICATION STRUCTURE BODY";
693 	}
694 	else if (elemID == 23)
695 	{
696 		qDebug() << "END APPLICATION STRUCTURE";
697 	}
698 	else
699 	{
700 		importRunning = false;
701 		qDebug() << "Class 0 ID" << elemID << "Len" << paramLen;
702 	}
703 }
704 
decodeClass1(QDataStream & ts,quint16 elemID,quint16 paramLen)705 void CgmPlug::decodeClass1(QDataStream &ts, quint16 elemID, quint16 paramLen)
706 {
707 	quint16 data;
708 	if (elemID == 1)
709 	{
710 		ts >> data;
711 		metaFileVersion = data;
712 		//qDebug() << "METAFILE VERSION" << data;
713 	}
714 	else if (elemID == 2)
715 		handleMetaFileDescription(getBinaryText(ts));
716 	else if (elemID == 3)
717 	{
718 		ts >> data;
719 		vdcType = data;
720 		//qDebug() << "VDC TYPE" << data;
721 	}
722 	else if (elemID == 4)
723 	{
724 		ts >> data;
725 		intPrecision = data;
726 	//	qDebug() << "INTEGER PRECISION" << data;
727 	}
728 	else if (elemID == 5)
729 	{
730 		ts >> data;
731 		realPrecision = data;
732 		ts >> data;
733 		realMantissa = data;
734 		ts >> data;
735 		realFraction = data;
736 		if (realPrecision == 0)
737 			realPrecisionSet = true;
738 	//	qDebug() << "REAL PRECISION" << realPrecision << realMantissa << realFraction;
739 	}
740 	else if (elemID == 6)
741 	{
742 		ts >> data;
743 		indexPrecision = data;
744 	//	qDebug() << "INDEX PRECISION" << indexPrecision;
745 	}
746 	else if (elemID == 7)
747 	{
748 		ts >> data;
749 		colorPrecision = data;
750 	//	qDebug() << "COLOUR PRECISION" << colorPrecision;
751 	}
752 	else if (elemID == 8)
753 	{
754 		ts >> data;
755 		colorIndexPrecision = data;
756 		//qDebug() << "COLOUR INDEX PRECISION" << colorIndexPrecision;
757 	}
758 	else if (elemID == 9)
759 	{
760 		ts >> data;
761 		maxColorIndex = data;
762 		// qDebug() << "MAXIMUM COLOUR INDEX" << maxColorIndex;
763 	}
764 	else if (elemID == 10)
765 	{
766 		if (m_colorModel == 1)		// RGB
767 		{
768 			if (colorPrecision == 8)
769 			{
770 				quint8 r, g, b;
771 				ts >> r >> g >> b;
772 				minColor = r;
773 				ts >> r >> g >> b;
774 				maxColor = r;
775 			}
776 			else if (colorPrecision == 16)
777 			{
778 				quint16 r, g, b;
779 				ts >> r >> g >> b;
780 				minColor = r;
781 				ts >> r >> g >> b;
782 				maxColor = r;
783 			}
784 		}
785 		else if (m_colorModel == 4)	// CMYK
786 		{
787 			if (colorPrecision == 8)
788 			{
789 				quint8 c, m, y, k;
790 				ts >> c >> m >> y >> k;
791 				minColor = c;
792 				ts >> c >> m >> y >> k;
793 				maxColor = c;
794 			}
795 			else if (colorPrecision == 16)
796 			{
797 				quint16 c, m, y, k;
798 				ts >> c >> m >> y >> k;
799 				minColor = c;
800 				ts >> c >> m >> y >> k;
801 				maxColor = c;
802 			}
803 		}
804 		// qDebug() << "COLOUR VALUE EXTENT" << minColor << maxColor;
805 	}
806 	else if (elemID == 11)
807 	{
808 	//	qDebug() << "METAFILE ELEMENT LIST";
809 	}
810 	else if (elemID == 12)
811 	{
812 		qDebug() << "METAFILE DEFAULTS REPLACEMENT" << paramLen;
813 	/*	quint16 data, elemClass, elemID, paramLenN;
814 		ts >> data;
815 		elemClass = (data & 0xF000) >> 12;
816 		elemID    = (data & 0x0FE0) >>  5;
817 		paramLenN  = data & 0x001F;
818 		if (paramLenN == 31)
819 			ts >> paramLenN;
820 		qDebug() << "CGM Command Class" << elemClass << "ID" << elemID << "ParamLen" << paramLenN;
821 		decodeBinary(ts, elemClass, elemID, paramLenN);*/
822 	}
823 	else if (elemID == 13)
824 	{
825 		quint16 bytesRead = 0;
826 		int fontID = 1;
827 		while (bytesRead < paramLen)
828 		{
829 			int posA = ts.device()->pos();
830 			QString p = getBinaryText(ts);
831 			int posN = ts.device()->pos();
832 			bytesRead += posN - posA;
833 			fontID_Map.insert(fontID, p);
834 		}
835 	//	qDebug() << "FONT LIST" << fontID_Map;
836 	}
837 	else if (elemID == 14)
838 	{
839 		qDebug() << "CHARACTER SET LIST";
840 	}
841 	else if (elemID == 15)
842 	{
843 		qDebug() << "CHARACTER CODING ANNOUNCER";
844 	}
845 	else if (elemID == 16)
846 	{
847 		ts >> data;
848 		namePrecision = data;
849  		// qDebug() << "NAME PRECISION" << namePrecision;
850 	}
851 	else if (elemID == 17)
852 	{
853 		QPointF max, min;
854 		max = getBinaryCoords(ts);
855 		min = getBinaryCoords(ts);
856 	//	qDebug() << "MAXIMUM VDC EXTENT" << min.x() << min.y() << max.x() << max.y();
857 	}
858 	else if (elemID == 18)
859 	{
860 		qDebug() << "SEGMENT PRIORITY EXTENT";
861 	}
862 	else if (elemID == 19)
863 	{
864 		ts >> data;
865 		m_colorModel = data;
866 	//	qDebug() << "COLOUR MODEL" << colorModel;
867 	}
868 	else if (elemID == 20)
869 	{
870 		qDebug() << "COLOUR CALIBRATION";
871 	}
872 	else if (elemID == 21)
873 	{
874 		qDebug() << "FONT PROPERTIES";
875 	}
876 	else if (elemID == 22)
877 	{
878 		qDebug() << "GLYPH MAPPING";
879 	}
880 	else if (elemID == 23)
881 	{
882 		qDebug() << "SYMBOL LIBRARY LIST";
883 	}
884 	else if (elemID == 24)
885 	{
886 		qDebug() << "PICTURE DIRECTORY";
887 	}
888 	else
889 	{
890 		importRunning = false;
891 		qDebug() << "Class 1 ID" << elemID << "Len" << paramLen;
892 	}
893 }
894 
decodeClass2(QDataStream & ts,quint16 elemID,quint16 paramLen)895 void CgmPlug::decodeClass2(QDataStream &ts, quint16 elemID, quint16 paramLen)
896 {
897 	quint16 data;
898 	if (elemID == 1)
899 	{
900 		ts >> data;
901 		metaFileScaleMode = data;
902 		double sc = 1.0;
903 		if (realPrecisionSet)
904 			sc = getBinaryReal(ts, 0, realMantissa);
905 		else
906 			sc = getBinaryReal(ts, 0, 9);
907 		if (metaFileScaleMode != 0)
908 			metaFileScale = sc;
909 	//	qDebug() << "SCALING MODE" << metaFileScaleMode << metaFileScale;
910 	}
911 	else if (elemID == 2)
912 	{
913 		ts >> data;
914 		colorMode = data;
915 //		qDebug() << "COLOUR SELECTION MODE" << colorMode;
916 	}
917 	else if (elemID == 3)
918 	{
919 		ts >> data;
920 		lineWidthMode = data;
921 		if (lineWidthMode == 0)
922 			lineWidth = 0; // qMax(vdcWidth, vdcHeight) / 1000;
923 		else if (lineWidthMode == 1)
924 			lineWidth = 1.0;
925 		else if (lineWidthMode == 2)
926 			lineWidth = 0.001;
927 		else if (lineWidthMode == 3)
928 			lineWidth = 0.35;
929 	//	qDebug() << "LINE WIDTH SPECIFICATION MODE" << lineWidthMode;
930 	}
931 	else if (elemID == 4)
932 	{
933 		ts >> data;
934 		markerSizeMode = data;
935 		// qDebug() << "MARKER SIZE SPECIFICATION MODE" << markerSizeMode;
936 	}
937 	else if (elemID == 5)
938 	{
939 		ts >> data;
940 		edgeWidthMode = data;
941 		if (edgeWidthMode == 0)
942 			edgeWidth = 0; // qMax(vdcWidth, vdcHeight) / 1000;
943 		else if (edgeWidthMode == 1)
944 			edgeWidth = 1.0;
945 		else if (edgeWidthMode == 2)
946 			edgeWidth = 0.001;
947 		else if (edgeWidthMode == 3)
948 			edgeWidth = 0.35;
949 	//	qDebug() << "EDGE WIDTH SPECIFICATION MODE" << edgeWidthMode;
950 	}
951 	else if (elemID == 6)
952 	{
953 		QPointF max, min;
954 		max = getBinaryCoords(ts, true);
955 		min = getBinaryCoords(ts, true);
956 		QRectF vd = QRectF(max, min);
957 		vcdFlippedV = (vd.height() > 0);
958 		vcdFlippedH = (vd.width() < 0);
959 		vd = vd.normalized();
960 		vdcWidth = vd.width();
961 		vdcHeight = vd.height();
962 		metaScale = 400.0 / qMax(vdcWidth, vdcHeight);
963 		if (lineWidthMode == 0)
964 			lineWidth = 0; // qMax(vdcWidth, vdcHeight) / 1000;
965 		else if (lineWidthMode == 1)
966 			lineWidth = 1.0;
967 		else if (lineWidthMode == 2)
968 			lineWidth = 0.001;
969 		else if (lineWidthMode == 3)
970 			lineWidth = 0.35;
971 		baseX = -vd.left() * metaScale;
972 		baseY = vd.top() * metaScale;
973 		vcdSet = true;
974 		if (!clipSet)
975 		{
976 			clipRect = QRectF(vd.left() * metaScale, vd.top() * metaScale, vdcWidth * metaScale, vdcHeight * metaScale);
977 			clipSet = true;
978 		}
979 	//	qDebug() << "VDC EXTENT" << vd.left() << vd.top() << vdcWidth << vdcHeight << vcdFlippedV;
980 	}
981 	else if (elemID == 7)
982 	{
983 		ScColor color = getBinaryDirectColor(ts);
984 		backgroundColor = handleColor(color, "FromCGM"+color.name());
985 		if (colorMode == 1)
986 			backgroundSet = true;
987 		else
988 			ColorTableMap.insert(0, backgroundColor);
989 //		qDebug() << "BACKGROUND COLOUR" << backgroundColor;
990 	}
991 	else if (elemID == 8)
992 	{
993 		QPointF max, min;
994 		max = getBinaryCoords(ts);
995 		min = getBinaryCoords(ts);
996 	//	qDebug() << "DEVICE VIEWPORT" << min.x() << min.y() << max.x() << max.y();
997 	}
998 	else if (elemID == 9)
999 	{
1000 		ts >> data;
1001 		viewPortScaleMode = data;
1002 		if (realPrecisionSet)
1003 			viewPortScale = getBinaryReal(ts, 0, realMantissa);
1004 		else
1005 			viewPortScale = getBinaryReal(ts, 0, 9);
1006 		// qDebug() << "DEVICE VIEWPORT SPECIFICATION MODE" << viewPortScaleMode << viewPortScale;
1007 	}
1008 	else if (elemID == 10)
1009 	{
1010 		qDebug() << "DEVICE VIEWPORT MAPPING";
1011 	}
1012 	else if (elemID == 11)
1013 	{
1014 		qDebug() << "LINE REPRESENTATION";
1015 	}
1016 	else if (elemID == 12)
1017 	{
1018 		qDebug() << "MARKER REPRESENTATION";
1019 	}
1020 	else if (elemID == 13)
1021 	{
1022 		qDebug() << "TEXT REPRESENTATION";
1023 	}
1024 	else if (elemID == 14)
1025 	{
1026 		qDebug() << "FILL REPRESENTATION";
1027 	}
1028 	else if (elemID == 15)
1029 	{
1030 		qDebug() << "EDGE REPRESENTATION";
1031 	}
1032 	else if (elemID == 16)
1033 	{
1034 		qDebug() << "INTERIOR STYLE SPECIFICATION MODE";
1035 	}
1036 	else if (elemID == 17)
1037 	{
1038 		qDebug() << "LINE AND EDGE TYPE DEFINITION";
1039 	}
1040 	else if (elemID == 18)
1041 	{
1042 		qDebug() << "HATCH STYLE DEFINITION";
1043 	}
1044 	else if (elemID == 19)
1045 	{
1046 		qDebug() << "GEOMETRIC PATTERN DEFINITION";
1047 	}
1048 	else if (elemID == 20)
1049 	{
1050 		qDebug() << "APPLICATION STRUCTURE DIRECTORY";
1051 	}
1052 	else
1053 	{
1054 		importRunning = false;
1055 		qDebug() << "Class 2 ID" << elemID << "Len" << paramLen;
1056 	}
1057 }
1058 
decodeClass3(QDataStream & ts,quint16 elemID,quint16 paramLen)1059 void CgmPlug::decodeClass3(QDataStream &ts, quint16 elemID, quint16 paramLen)
1060 {
1061 	quint16 data;
1062 	if (elemID == 1)
1063 	{
1064 		ts >> data;
1065 		vdcInt = data;
1066  		// qDebug() << "VDC INTEGER PRECISION" << vdcInt;
1067 	}
1068 	else if (elemID == 2)
1069 	{
1070 		ts >> data;
1071 		vdcReal = data;
1072 		ts >> data;
1073 		vdcMantissa = data;
1074 		ts >> data;
1075  		// qDebug() << "VDC REAL PRECISION" << vdcReal << vdcMantissa;
1076 	}
1077 	else if (elemID == 3)
1078 	{
1079 		qDebug() << "AUXILIARY COLOUR";
1080 	}
1081 	else if (elemID == 4)
1082 	{
1083 		qDebug() << "TRANSPARENCY";
1084 	}
1085 	else if (elemID == 5)
1086 	{
1087 		QPointF max, min;
1088 		max = getBinaryCoords(ts);
1089 		min = getBinaryCoords(ts);
1090 		QRectF vd = QRectF(max, min);
1091 		vd = vd.normalized();
1092 		double w = convertCoords(vd.width());
1093 		double h = convertCoords(vd.height());
1094 		double x = convertCoords(vd.left());
1095 		double y = convertCoords(vd.top());
1096 		x += m_Doc->currentPage()->xOffset();
1097 		y += m_Doc->currentPage()->yOffset();
1098 		clipRect = QRectF(x, y, w, h);
1099 		clipSet = true;
1100 	//	qDebug() << "CLIP RECTANGLE" << clipRect;
1101 	}
1102 	else if (elemID == 6)
1103 	{
1104 		ts >> data;
1105 		useClipRect = (data != 0);
1106 		// qDebug() << "CLIP INDICATOR" << useClipRect;
1107 	}
1108 	else if (elemID == 7)
1109 	{
1110 		qDebug() << "LINE CLIPPING MODE";
1111 	}
1112 	else if (elemID == 8)
1113 	{
1114 		qDebug() << "MARKER CLIPPING MODE";
1115 	}
1116 	else if (elemID == 9)
1117 	{
1118 		qDebug() << "EDGE CLIPPING MODE";
1119 	}
1120 	else if (elemID == 10)
1121 	{
1122 		if (recordRegion)
1123 			regionPath.closeSubpath();
1124 		if (recordFigure)
1125 			figurePath.closeSubpath();
1126 		figClose = true;
1127 	//	qDebug() << "NEW REGION";
1128 	}
1129 	else if (elemID == 11)
1130 	{
1131 		qDebug() << "SAVE PRIMITIVE CONTEXT";
1132 	}
1133 	else if (elemID == 12)
1134 	{
1135 		qDebug() << "RESTORE PRIMITIVE CONTEXT";
1136 	}
1137 	else if (elemID == 17)
1138 	{
1139 		uint index = getBinaryUInt(ts, indexPrecision);
1140 		uint type = getBinaryUInt(ts, indexPrecision);
1141 		if (type == 1)
1142 		{
1143 			if (groupStack.count() != 0)
1144 			{
1145 				QList<PageItem*> gElements = groupStack.pop();
1146 				tmpSel->clear();
1147 				if (gElements.count() > 0)
1148 				{
1149 					for (int dre = 0; dre < gElements.count(); ++dre)
1150 					{
1151 						tmpSel->addItem(gElements.at(dre), true);
1152 						Elements.removeAll(gElements.at(dre));
1153 					}
1154 					PageItem *ite = m_Doc->itemSelection_GroupObjects(false, false, tmpSel);
1155 					QPainterPath clip = regionMap[index];
1156 					if (!clip.isEmpty())
1157 					{
1158 						ite->PoLine.fromQPainterPath(clip);
1159 						ite->PoLine.translate(-ite->xPos(), -ite->yPos());
1160 						ite->PoLine.translate(baseX, baseY);
1161 					}
1162 					tmpSel->clear();
1163 					tmpSel->addItem(ite, true);
1164 					Elements.append(ite);
1165 				}
1166 				if (groupStack.count() != 0)
1167 				{
1168 					for (int as = 0; as < tmpSel->count(); ++as)
1169 					{
1170 						groupStack.top().append(tmpSel->itemAt(as));
1171 					}
1172 				}
1173 				tmpSel->clear();
1174 			}
1175 		}
1176 		else if ((type == 2) || (type == 3))
1177 		{
1178 			QList<PageItem*> gElements;
1179 			groupStack.push(gElements);
1180 		}
1181 		// qDebug() << "PROTECTION REGION INDICATOR" << index << type;
1182 	}
1183 	else if (elemID == 18)
1184 	{
1185 		qDebug() << "GENERALIZED TEXT PATH MODE";
1186 	}
1187 	else if (elemID == 19)
1188 	{
1189 		qDebug() << "MITRE LIMIT";
1190 	}
1191 	else if (elemID == 20)
1192 	{
1193 		qDebug() << "TRANSPARENT CELL COLOUR";
1194 	}
1195 	else
1196 	{
1197 		importRunning = false;
1198 		qDebug() << "Class 3 ID" << elemID << "Len" << paramLen;
1199 	}
1200 }
1201 
decodeClass4(QDataStream & ts,quint16 elemID,quint16 paramLen)1202 void CgmPlug::decodeClass4(QDataStream &ts, quint16 elemID, quint16 paramLen)
1203 {
1204 	if (elemID == 1)
1205 	{
1206 		getBinaryPath(ts, paramLen);
1207 		if (Coords.size() > 3)
1208 		{
1209 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1210 			if (recordRegion)
1211 				regionPath.connectPath(Coords.toQPainterPath(false));
1212 			else
1213 			{
1214 				if (recordFigure)
1215 				{
1216 					if (figClose)
1217 					{
1218 						QPainterPath ell = Coords.toQPainterPath(false);
1219 						appendPath(figurePath, ell);
1220 						figClose = false;
1221 					}
1222 					else
1223 						figurePath.connectPath(Coords.toQPainterPath(false));
1224 				}
1225 				int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, lineWidth, CommonStrings::None, lineColor);
1226 				PageItem *ite = m_Doc->Items->at(z);
1227 				ite->PoLine = Coords.copy();
1228 				finishItem(ite);
1229 			}
1230 		}
1231 		// qDebug() << "POLYLINE";
1232 	}
1233 	else if (elemID == 2)
1234 	{
1235 		getBinaryPath(ts, paramLen, true);
1236 		if (Coords.size() > 3)
1237 		{
1238 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1239 			if (recordRegion)
1240 				regionPath.connectPath(Coords.toQPainterPath(false));
1241 			else
1242 			{
1243 				if (recordFigure)
1244 				{
1245 					if (figClose)
1246 					{
1247 						QPainterPath ell = Coords.toQPainterPath(false);
1248 						appendPath(figurePath, ell);
1249 						figClose = false;
1250 					}
1251 					else
1252 						figurePath.connectPath(Coords.toQPainterPath(false));
1253 				}
1254 				int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, lineWidth, CommonStrings::None, lineColor);
1255 				PageItem *ite = m_Doc->Items->at(z);
1256 				ite->PoLine = Coords.copy();
1257 				finishItem(ite);
1258 			}
1259 		}
1260 		// qDebug() << "DISJOINT POLYLINE";
1261 	}
1262 	else if (elemID == 3)
1263 	{
1264 		qDebug() << "POLYMARKER";
1265 	}
1266 	else if (elemID == 4)
1267 	{
1268 		QPointF center = getBinaryCoords(ts);
1269 		double txX = convertCoords(center.x());
1270 		double txY = convertCoords(center.y());
1271 		quint16 flag;
1272 		ts >> flag;
1273 		QString txt = getBinaryText(ts);
1274 		QPainterPath ell;
1275 		ell.addText(0, 0, QFont(fontID_Map[m_fontIndex], textSize), txt);
1276 		ell.translate(txX, txY);
1277 		if (textAlignH == 2)
1278 			ell.translate(-ell.boundingRect().width() / 2.0, 0);
1279 		else if (textAlignH == 3)
1280 			ell.translate(-ell.boundingRect().width(), 0);
1281 		ell.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1282 		if (recordRegion)
1283 			regionPath.addPath(ell);
1284 		else
1285 		{
1286 			if (recordFigure)
1287 				figurePath.addPath(ell);
1288 			Coords.fromQPainterPath(ell, true);
1289 			int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, textColor, CommonStrings::None);
1290 			PageItem *ite = m_Doc->Items->at(z);
1291 			ite->PoLine = Coords.copy();
1292 			finishItem(ite, false);
1293 		}
1294 	//	qDebug() << "TEXT Len" << textAlignH;
1295 	}
1296 	else if (elemID == 5)
1297 	{
1298 		double sx = convertCoords(getBinaryDistance(ts));
1299 		double sy = convertCoords(getBinaryDistance(ts));
1300 		QPointF center = getBinaryCoords(ts);
1301 		double txX = convertCoords(center.x());
1302 		double txY = convertCoords(center.y());
1303 		quint16 flag;
1304 		ts >> flag;
1305 		QString txt = getBinaryText(ts);
1306 		QPainterPath ell;
1307 		ell.addText(0, 0, QFont(fontID_Map[m_fontIndex], textSize), txt);
1308 		double scx = sx / ell.boundingRect().width();
1309 		double scy = sy / ell.boundingRect().height();
1310 		if ((textScaleMode > 1) || ((ell.boundingRect().width() > sx) || (ell.boundingRect().height() > sy)))
1311 		{
1312 			QTransform mm;
1313 			mm.scale(scx, scy);
1314 			ell = mm.map(ell);
1315 		}
1316 		ell.translate(txX, txY);
1317 		if (textAlignH == 2)
1318 			ell.translate(-ell.boundingRect().width() / 2.0, 0);
1319 		else if (textAlignH == 3)
1320 			ell.translate(-ell.boundingRect().width(), 0);
1321 		ell.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1322 		if (recordRegion)
1323 			regionPath.addPath(ell);
1324 		else
1325 		{
1326 			if (recordFigure)
1327 				figurePath.addPath(ell);
1328 			Coords.fromQPainterPath(ell, true);
1329 			int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, textColor, CommonStrings::None);
1330 			PageItem *ite = m_Doc->Items->at(z);
1331 			ite->PoLine = Coords.copy();
1332 			finishItem(ite, false);
1333 		}
1334 	//	qDebug() << "RESTRICTED TEXT";
1335 	}
1336 	else if (elemID == 6)
1337 	{
1338 		qDebug() << "APPEND TEXT";
1339 	}
1340 	else if (elemID == 7)
1341 	{
1342 		getBinaryPath(ts, paramLen);
1343 		if (Coords.size() > 3)
1344 		{
1345 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1346 			if (recordRegion)
1347 				regionPath.addPath(Coords.toQPainterPath(true));
1348 			else
1349 			{
1350 				if (recordFigure)
1351 					figurePath.addPath(Coords.toQPainterPath(true));
1352 				PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, edgeWidth, fillColor, edgeColor);
1353 				ite->PoLine = Coords.copy();
1354 				finishItem(ite, false);
1355 			}
1356 		}
1357 		// qDebug() << "POLYGON";
1358 	}
1359 	else if (elemID == 8)
1360 	{
1361 	//	qDebug() << "POLYGON SET" << "Fill Type" << fillType;
1362 		quint16 bytesRead = 0;
1363 		bool first = true;
1364 		Coords.resize(0);
1365 		Coords.svgInit();
1366 		quint16 flag;
1367 		paramLen = paramLen & 0x7FFF;
1368 		QPainterPath polySetPath;
1369 		QPointF startPoint;
1370 		while (bytesRead < paramLen)
1371 		{
1372 			int posA = ts.device()->pos();
1373 			QPointF p = getBinaryCoords(ts);
1374 			ts >> flag;
1375 			int posN = ts.device()->pos();
1376 			bytesRead += posN - posA;
1377 			if (first)
1378 			{
1379 				polySetPath.moveTo(convertCoords(p.x()), convertCoords(p.y()));
1380 				startPoint = p;
1381 				first = false;
1382 			}
1383 			else
1384 				polySetPath.lineTo(convertCoords(p.x()), convertCoords(p.y()));
1385 			if ((flag == 2) || (flag == 3))
1386 			{
1387 				polySetPath.lineTo(convertCoords(startPoint.x()), convertCoords(startPoint.y()));
1388 				polySetPath.closeSubpath();
1389 				first = true;
1390 			}
1391 		}
1392 		polySetPath.lineTo(convertCoords(startPoint.x()), convertCoords(startPoint.y()));
1393 		polySetPath.closeSubpath();
1394 		if (recordFigure)
1395 		{
1396 			polySetPath.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1397 			figurePath.addPath(polySetPath);
1398 		}
1399 		else
1400 		{
1401 		//	qDebug() << "POLYGON SET" << "Fill Color" << fillColor;
1402 			Coords.fromQPainterPath(polySetPath, true);
1403 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, edgeWidth, fillColor, edgeColor);
1404 			ite->PoLine = Coords.copy();
1405 			ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1406 			finishItem(ite, false);
1407 		}
1408 	}
1409 	else if (elemID == 9)
1410 	{
1411 		int pos = ts.device()->pos();
1412 		QPointF p, q, r;
1413 		int nx, ny;
1414 		quint16 mode;
1415 		p = convertCoords(getBinaryCoords(ts));
1416 		q = convertCoords(getBinaryCoords(ts));
1417 		r = convertCoords(getBinaryCoords(ts));
1418 		nx = getBinaryUInt(ts, intPrecision);
1419 		ny = getBinaryUInt(ts, intPrecision);
1420 		int t_colorPrecision = colorPrecision;
1421 		int t_colorIndexPrecision = colorIndexPrecision;
1422 		colorPrecision = getBinaryUInt(ts, intPrecision);
1423 		colorIndexPrecision = colorPrecision;
1424 //		qDebug() << "CELL ARRAY at" << pos << "Size" << nx << ny << "Compression" << mode << "Color Prec" << colorPrecision;
1425 		if (colorPrecision == 0)
1426 		{
1427 			colorPrecision = t_colorPrecision;
1428 			colorIndexPrecision = t_colorIndexPrecision;
1429 		}
1430 		ts >> mode;
1431 		int bytesRead = ts.device()->pos() - pos;
1432 		QLineF pr = QLineF(p, r);
1433 		QLineF rq = QLineF(r, q);
1434 		double originX = p.x();
1435 		double originY = p.y();
1436 		bool flipX = false;
1437 		bool flipY = false;
1438 		if (p.x() > r.x())
1439 		{
1440 			flipX = true;
1441 			originX = r.x();
1442 		}
1443 		if (p.y() > q.y())
1444 		{
1445 			flipY = true;
1446 			originY = q.y();
1447 		}
1448 		int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, baseX + originX, baseY + originY, pr.length(), rq.length(), edgeWidth, CommonStrings::None, CommonStrings::None);
1449 		PageItem *ite = m_Doc->Items->at(z);
1450 		ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1451 		finishItem(ite, false);
1452 		QImage image = QImage(nx, ny, QImage::Format_ARGB32);
1453 		quint16 flag = paramLen & 0x8000;
1454 		quint16 pLen = (paramLen & 0x7FFF) - bytesRead;
1455 		QByteArray imageData;
1456 		imageData.resize(0);
1457 		QByteArray rD = ts.device()->read(pLen);
1458 		imageData.append(rD);
1459 		while (flag)
1460 		{
1461 			ts >> pLen;
1462 			flag = pLen & 0x8000;
1463 			pLen = pLen & 0x7FFF;
1464 			QByteArray rD = ts.device()->read(pLen);
1465 			imageData.append(rD);
1466 		}
1467 		if (colorPrecision < 8)
1468 		{
1469 			ScBitReader *breader = new ScBitReader(imageData);
1470 			for (int yy = 0; yy < ny; yy++)
1471 			{
1472 				ScColor color;
1473 				QRgb *s = (QRgb*)(image.scanLine(yy));
1474 				if (mode == 1)
1475 				{
1476 					for (int xx = 0; xx < nx; xx++)
1477 					{
1478 						if (colorMode == 0)
1479 							color = m_Doc->PageColors[getBinaryIndexedColor(breader)];
1480 						else
1481 							color = getBinaryDirectColor(breader);
1482 						QColor co = color.getRawRGBColor();
1483 						*s++ = qRgba(co.red(), co.green(), co.blue(), 255);
1484 					}
1485 				}
1486 				else
1487 				{
1488 					int xx = 0;
1489 					while (xx < nx)
1490 					{
1491 						int counter = breader->getUInt(intPrecision);
1492 						if ((counter > nx) || (counter == 0))
1493 						{
1494 							importRunning = false;
1495 							return;
1496 						}
1497 						if (colorMode == 0)
1498 							color = m_Doc->PageColors[getBinaryIndexedColor(breader)];
1499 						else
1500 							color = getBinaryDirectColor(breader);
1501 						QColor co = color.getRawRGBColor();
1502 						for (int xc = 0; xc < counter; xc++)
1503 						{
1504 							*s++ = qRgba(co.red(), co.green(), co.blue(), 255);
1505 							xx++;
1506 							if (xx >= nx)
1507 								break;
1508 						}
1509 					}
1510 				}
1511 				breader->alignToWord();
1512 			}
1513 		}
1514 		else
1515 		{
1516 			QDataStream istr(imageData);
1517 			istr.setByteOrder(QDataStream::BigEndian);
1518 			for (int yy = 0; yy < ny; yy++)
1519 			{
1520 				ScColor color;
1521 				QRgb *s = (QRgb*)(image.scanLine(yy));
1522 				if (mode == 1)
1523 				{
1524 					for (int xx = 0; xx < nx; xx++)
1525 					{
1526 						if (colorMode == 0)
1527 							color = m_Doc->PageColors[getBinaryIndexedColor(istr)];
1528 						else
1529 							color = getBinaryDirectColor(istr);
1530 						QColor co = color.getRawRGBColor();
1531 						*s++ = qRgba(co.red(), co.green(), co.blue(), 255);
1532 					}
1533 				}
1534 				else
1535 				{
1536 					int xx = 0;
1537 					while (xx < nx)
1538 					{
1539 						int counter = getBinaryUInt(istr, intPrecision);
1540 						if ((counter > nx) || (counter == 0))
1541 						{
1542 							importRunning = false;
1543 							return;
1544 						}
1545 						if (colorMode == 0)
1546 							color = m_Doc->PageColors[getBinaryIndexedColor(istr)];
1547 						else
1548 							color = getBinaryDirectColor(istr);
1549 						QColor co = color.getRawRGBColor();
1550 						for (int xc = 0; xc < counter; xc++)
1551 						{
1552 							*s++ = qRgba(co.red(), co.green(), co.blue(), 255);
1553 							xx++;
1554 							if (xx >= nx)
1555 								break;
1556 						}
1557 					}
1558 				}
1559 				uint adj = istr.device()->pos() % 2;
1560 				if (adj != 0)
1561 					istr.skipRawData(1);
1562 			}
1563 		}
1564 		QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_cgm_XXXXXX.png");
1565 		tempFile->setAutoRemove(false);
1566 		tempFile->open();
1567 		QString fileName = getLongPathName(tempFile->fileName());
1568 		tempFile->close();
1569 		ite->isInlineImage = true;
1570 		ite->isTempFile = true;
1571 		image.save(fileName, "PNG");
1572 		if ((image.width() < 20) || image.height() < 20)
1573 			ite->pixm.imgInfo.lowResType = 0;
1574 		m_Doc->loadPict(fileName, ite);
1575 		delete tempFile;
1576 		ite->setImageFlippedH(flipX);
1577 		ite->setImageFlippedV(flipY);
1578 		ite->setImageScalingMode(false, false);
1579 		ite->adjustPictScale();
1580 		colorPrecision = t_colorPrecision;
1581 		colorIndexPrecision = t_colorIndexPrecision;
1582 	}
1583 	else if (elemID == 10)
1584 	{
1585 		qDebug() << "GENERALIZED DRAWING PRIMITIVE";
1586 	}
1587 	else if (elemID == 11)
1588 	{
1589 		QPointF max, min;
1590 		max = getBinaryCoords(ts);
1591 		min = getBinaryCoords(ts);
1592 		QRectF vd = QRectF(max, min);
1593 		vd = vd.normalized();
1594 		double w = convertCoords(vd.width());
1595 		double h = convertCoords(vd.height());
1596 		double x = convertCoords(vd.left());
1597 		double y = convertCoords(vd.top());
1598 		if (recordRegion)
1599 			regionPath.addRect(QRectF(x + m_Doc->currentPage()->xOffset(), y + m_Doc->currentPage()->yOffset(), w, h));
1600 		else
1601 		{
1602 			if (recordFigure)
1603 				figurePath.addRect(QRectF(x + m_Doc->currentPage()->xOffset(), y + m_Doc->currentPage()->yOffset(), w, h));
1604 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + x, baseY + y, w, h, edgeWidth, fillColor, edgeColor);
1605 			ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1606 			finishItem(ite, false);
1607 		}
1608 	//	qDebug() << "RECTANGLE";
1609 	}
1610 	else if (elemID == 12)
1611 	{
1612 		QPointF max = getBinaryCoords(ts);
1613 		double x = convertCoords(max.x());
1614 		double y = convertCoords(max.y());
1615 		double r = convertCoords(getBinaryDistance(ts));
1616 		x = x - r;
1617 		y = y - r;
1618 		if (recordRegion)
1619 			regionPath.addEllipse(QPointF(x + m_Doc->currentPage()->xOffset(), y + m_Doc->currentPage()->yOffset()), r * 2.0, r * 2.0);
1620 		else
1621 		{
1622 			if (recordFigure)
1623 				figurePath.addEllipse(QRectF(x + m_Doc->currentPage()->xOffset(), y + m_Doc->currentPage()->yOffset(), r * 2.0, r * 2.0));
1624 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + x, baseY + y, r * 2.0, r * 2.0, edgeWidth, fillColor, edgeColor);
1625 			ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1626 			finishItem(ite, false);
1627 		}
1628 	//	qDebug() << "CIRCLE";
1629 	}
1630 	else if (elemID == 13)
1631 	{
1632 		QPointF pStart = convertCoords(getBinaryCoords(ts));
1633 		QPointF pInter = convertCoords(getBinaryCoords(ts));
1634 		QPointF pEnd = convertCoords(getBinaryCoords(ts));
1635 		QLineF s_e = QLineF(pStart, pEnd);
1636 		QLineF n_s = s_e.normalVector();
1637 		n_s.translate(s_e.pointAt(0.5) - s_e.p1());
1638 		QLineF s_i = QLineF(pStart, pInter);
1639 		QLineF n_i = s_i.normalVector();
1640 		n_i.translate(s_i.pointAt(0.5) - s_i.p1());
1641 		QPointF center;
1642 		if (n_s.intersects(n_i, &center) != QLineF::NoIntersection)
1643 		{
1644 			QLineF rad1 = QLineF(center, pStart);
1645 			QLineF rad3 = QLineF(center, pInter);
1646 			double radius = rad1.length();
1647 			Coords.resize(0);
1648 			Coords.svgInit();
1649 			Coords.svgMoveTo(pStart.x(), pStart.y());
1650 			Coords.svgArcTo(radius, radius, 0, false, rad1.angle() >= rad3.angle(), pInter.x(), pInter.y());
1651 			Coords.svgArcTo(radius, radius, 0, false, rad1.angle() >= rad3.angle(), pEnd.x(), pEnd.y());
1652 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1653 			if (recordRegion)
1654 				regionPath.connectPath(Coords.toQPainterPath(false));
1655 			else
1656 			{
1657 				if (recordFigure)
1658 				{
1659 					if (figClose)
1660 					{
1661 						QPainterPath ell = Coords.toQPainterPath(false);
1662 						appendPath(figurePath, ell);
1663 						figClose = false;
1664 					}
1665 					else
1666 						figurePath.connectPath(Coords.toQPainterPath(false));
1667 				}
1668 				int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, lineWidth, CommonStrings::None, lineColor);
1669 				PageItem *ite = m_Doc->Items->at(z);
1670 				ite->PoLine = Coords.copy();
1671 				finishItem(ite);
1672 			}
1673 		}
1674 	//	qDebug() << "CIRCULAR ARC 3 POINT";
1675 	}
1676 	else if (elemID == 14)
1677 	{
1678 		QPointF pStart = convertCoords(getBinaryCoords(ts));
1679 		QPointF pInter = convertCoords(getBinaryCoords(ts));
1680 		QPointF pEnd = convertCoords(getBinaryCoords(ts));
1681 		quint16 mode;
1682 		ts >> mode;
1683 		QLineF s_e = QLineF(pStart, pEnd);
1684 		QLineF n_s = s_e.normalVector();
1685 		n_s.translate(s_e.pointAt(0.5) - s_e.p1());
1686 		QLineF s_i = QLineF(pStart, pInter);
1687 		QLineF n_i = s_i.normalVector();
1688 		n_i.translate(s_i.pointAt(0.5) - s_i.p1());
1689 		QPointF center;
1690 		if (n_s.intersects(n_i, &center) != QLineF::NoIntersection)
1691 		{
1692 			QLineF rad1 = QLineF(center, pStart);
1693 			QLineF rad3 = QLineF(center, pInter);
1694 			double radius = rad1.length();
1695 			Coords.resize(0);
1696 			Coords.svgInit();
1697 			if (mode == 0)
1698 			{
1699 				Coords.svgMoveTo(center.x(), center.y());
1700 				Coords.svgLineTo(pStart.x(), pStart.y());
1701 			}
1702 			else
1703 				Coords.svgMoveTo(pStart.x(), pStart.y());
1704 			Coords.svgArcTo(radius, radius, 0, false, rad1.angle() >= rad3.angle(), pInter.x(), pInter.y());
1705 			Coords.svgArcTo(radius, radius, 0, false, rad1.angle() >= rad3.angle(), pEnd.x(), pEnd.y());
1706 			if (mode == 0)
1707 				Coords.svgLineTo(center.x(), center.y());
1708 			else
1709 				Coords.svgLineTo(pStart.x(), pStart.y());
1710 			Coords.svgClosePath();
1711 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1712 			if (recordRegion)
1713 				regionPath.addPath(Coords.toQPainterPath(false));
1714 			else
1715 			{
1716 				if (recordFigure)
1717 					figurePath.addPath(Coords.toQPainterPath(false));
1718 				PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, edgeWidth, fillColor, edgeColor);
1719 				ite->PoLine = Coords.copy();
1720 				finishItem(ite, false);
1721 			}
1722 		}
1723 	//	qDebug() << "CIRCULAR ARC 3 POINT CLOSE";
1724 	}
1725 	else if (elemID == 15)
1726 	{
1727 		QPointF center = getBinaryCoords(ts);
1728 		double sx = convertCoords(getBinaryDistance(ts));
1729 		double sy = convertCoords(getBinaryDistance(ts));
1730 		double ex = convertCoords(getBinaryDistance(ts));
1731 		double ey = convertCoords(getBinaryDistance(ts));
1732 		double r = convertCoords(getBinaryDistance(ts));
1733 		double cx = convertCoords(center.x()) + m_Doc->currentPage()->xOffset();
1734 		double cy = convertCoords(center.y()) + m_Doc->currentPage()->yOffset();
1735 		if (vcdFlippedV)
1736 		{
1737 			sy *= -1;
1738 			ey *= -1;
1739 		}
1740 		if (vcdFlippedH)
1741 		{
1742 			sx *= -1;
1743 			ex *= -1;
1744 		}
1745 		QLineF stv = QLineF(cx, cy, cx + sx, cy + sy);
1746 		QLineF env = QLineF(cx, cy, cx + ex, cy + ey);
1747 		QPainterPath ell;
1748 		if (qFuzzyCompare(sx, ex) && qFuzzyCompare(sy, ey))
1749 		{
1750 			ell.addEllipse(QPointF(cx, cy), r, r);
1751 		}
1752 		else
1753 		{
1754 			stv.setLength(r);
1755 			ell.moveTo(stv.p2().x(), stv.p2().y());
1756 			ell.arcTo(cx - r, cy - r, r * 2.0, r * 2.0, stv.angle(), stv.angleTo(env));
1757 		}
1758 		if (recordRegion)
1759 			regionPath.connectPath(ell);
1760 		else
1761 		{
1762 			if (recordFigure)
1763 			{
1764 				if (figClose)
1765 				{
1766 					appendPath(figurePath, ell);
1767 					figClose = false;
1768 				}
1769 				else
1770 					figurePath.connectPath(ell);
1771 			}
1772 			Coords.fromQPainterPath(ell, false);
1773 			int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, lineWidth, CommonStrings::None, lineColor);
1774 			PageItem *ite = m_Doc->Items->at(z);
1775 			ite->PoLine = Coords.copy();
1776 			finishItem(ite);
1777 		}
1778 	//	qDebug() << "CIRCULAR ARC CENTRE";
1779 	}
1780 	else if (elemID == 16)
1781 	{
1782 		quint16 mode;
1783 		QPointF center = getBinaryCoords(ts);
1784 		double sx = convertCoords(getBinaryDistance(ts));
1785 		double sy = convertCoords(getBinaryDistance(ts));
1786 		double ex = convertCoords(getBinaryDistance(ts));
1787 		double ey = convertCoords(getBinaryDistance(ts));
1788 		double r = convertCoords(getBinaryDistance(ts));
1789 		ts >> mode;
1790 		double cx = convertCoords(center.x()) + m_Doc->currentPage()->xOffset();
1791 		double cy = convertCoords(center.y()) + m_Doc->currentPage()->yOffset();
1792 		if (vcdFlippedV)
1793 		{
1794 			sy *= -1;
1795 			ey *= -1;
1796 		}
1797 		if (vcdFlippedH)
1798 		{
1799 			sx *= -1;
1800 			ex *= -1;
1801 		}
1802 		QLineF stv = QLineF(cx, cy, cx + sx, cy + sy);
1803 		QLineF env = QLineF(cx, cy, cx + ex, cy + ey);
1804 		QPainterPath ell;
1805 		if (qFuzzyCompare(sx, ex) && qFuzzyCompare(sy, ey))
1806 		{
1807 			ell.addEllipse(QPointF(cx, cy), r, r);
1808 		}
1809 		else
1810 		{
1811 			stv.setLength(r);
1812 			if (mode == 0)
1813 			{
1814 				ell.moveTo(cx, cy);
1815 				ell.arcTo(cx - r, cy - r, r * 2.0, r * 2.0, stv.angle(), stv.angleTo(env));
1816 				ell.lineTo(cx, cy);
1817 				ell.closeSubpath();
1818 			}
1819 			else
1820 			{
1821 				ell.moveTo(stv.p2().x(), stv.p2().y());
1822 				ell.arcTo(cx - r, cy - r, r * 2.0, r * 2.0, stv.angle(), stv.angleTo(env));
1823 				ell.lineTo(stv.p2().x(), stv.p2().y());
1824 				ell.closeSubpath();
1825 			}
1826 		}
1827 		if (recordRegion)
1828 			regionPath.addPath(ell);
1829 		else
1830 		{
1831 			if (recordFigure)
1832 				figurePath.addPath(ell);
1833 			Coords.fromQPainterPath(ell, true);
1834 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, edgeWidth, fillColor, edgeColor);
1835 			ite->PoLine = Coords.copy();
1836 			finishItem(ite, false);
1837 		}
1838 	//	qDebug() << "CIRCULAR ARC CENTRE CLOSE";
1839 	}
1840 	else if (elemID == 17)
1841 	{
1842 		QPointF center, r1, r2;
1843 		center = getBinaryCoords(ts);
1844 		double cx = convertCoords(center.x());
1845 		double cy = convertCoords(center.y());
1846 		r1 = getBinaryCoords(ts);
1847 		double r1x = convertCoords(r1.x());
1848 		double r1y = convertCoords(r1.y());
1849 		r2 = getBinaryCoords(ts);
1850 		double r2x = convertCoords(r2.x());
1851 		double r2y = convertCoords(r2.y());
1852 		double distX = distance(r1x - cx, r1y - cy);
1853 		double distY = distance(r2x - cx, r2y - cy);
1854 		double rotB = xy2Deg(r1x - cx, r1y - cy);
1855 		QPainterPath ell;
1856 		ell.addEllipse(QPointF(0, 0), distX, distY);
1857 		QTransform mm;
1858 		mm.rotate(rotB);
1859 		ell = mm.map(ell);
1860 		ell.translate(cx, cy);
1861 		if (recordRegion)
1862 		{
1863 			ell.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1864 			regionPath.addPath(ell);
1865 		}
1866 		else
1867 		{
1868 			ell.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1869 			if (recordFigure)
1870 				figurePath.addPath(ell);
1871 			Coords.fromQPainterPath(ell, true);
1872 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, edgeWidth, fillColor, edgeColor);
1873 			ite->PoLine = Coords.copy();
1874 			finishItem(ite, false);
1875 		}
1876 	//	qDebug() << "ELLIPSE";
1877 	}
1878 	else if (elemID == 18)
1879 	{
1880 		QPointF center = getBinaryCoords(ts);
1881 		double cx = convertCoords(center.x());
1882 		double cy = convertCoords(center.y());
1883 		QPointF r1 = getBinaryCoords(ts);
1884 		double r1x = convertCoords(r1.x());
1885 		double r1y = convertCoords(r1.y());
1886 		QPointF r2 = getBinaryCoords(ts);
1887 		double r2x = convertCoords(r2.x());
1888 		double r2y = convertCoords(r2.y());
1889 		QLineF dstX = QLineF(cx, cy, r1x, r1y);
1890 		QLineF dstY = QLineF(cx, cy, r2x, r2y);
1891 		double distX = dstX.length();
1892 		double distY = dstY.length();
1893 		double rotB = dstX.angle();
1894 		double sx = convertCoords(getBinaryDistance(ts));
1895 		double sy = convertCoords(getBinaryDistance(ts));
1896 		double ex = convertCoords(getBinaryDistance(ts));
1897 		double ey = convertCoords(getBinaryDistance(ts));
1898 		if (vcdFlippedV)
1899 		{
1900 			sy *= -1;
1901 			ey *= -1;
1902 		}
1903 		if (vcdFlippedH)
1904 		{
1905 			sx *= -1;
1906 			ex *= -1;
1907 		}
1908 		QLineF stv = QLineF(cx, cy, cx + sx, cy + sy);
1909 		QLineF env = QLineF(cx, cy, cx + ex, cy + ey);
1910 		QPainterPath ell;
1911 		ell.addEllipse(QPointF(cx, cy), distX, distY);
1912 		ell.translate(-cx, -cy);
1913 		QTransform mm;
1914 		mm.rotate(rotB);
1915 		ell = mm.map(ell);
1916 		ell.translate(cx, cy);
1917 		QPolygonF elPo = ell.toFillPolygon();
1918 		QPointF stP = stv.p2();
1919 		QPointF enP = env.p2();
1920 		if (qFuzzyCompare(sx, ex) && qFuzzyCompare(sy, ey))
1921 		{
1922 			ell.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1923 			Coords.fromQPainterPath(ell);
1924 		}
1925 		else
1926 		{
1927 			for (int a = 0; a < elPo.size() - 1; a++)
1928 			{
1929 				QPointF intersect;
1930 				if (QLineF(elPo[a], elPo[a+1]).intersects(stv, &intersect) == QLineF::BoundedIntersection)
1931 				{
1932 					stP = intersect;
1933 					break;
1934 				}
1935 			}
1936 			for (int a = 0; a < elPo.size() - 1; a++)
1937 			{
1938 				QPointF intersect;
1939 				if (QLineF(elPo[a], elPo[a+1]).intersects(env, &intersect) == QLineF::BoundedIntersection)
1940 				{
1941 					enP = intersect;
1942 					break;
1943 				}
1944 			}
1945 			Coords.resize(0);
1946 			Coords.svgInit();
1947 			if (dstX.angleTo(dstY) > 180)
1948 			{
1949 				Coords.svgMoveTo(stP.x(), stP.y());
1950 				Coords.svgArcTo(distX, distY, rotB, stv.angleTo(env) < 180, dstX.angleTo(dstY) > 180, enP.x(), enP.y());
1951 			}
1952 			else
1953 			{
1954 				Coords.svgMoveTo(stP.x(), stP.y());
1955 				Coords.svgArcTo(distX, distY, rotB, stv.angleTo(env) > 180, dstX.angleTo(dstY) > 180, enP.x(), enP.y());
1956 			}
1957 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1958 			ell = Coords.toQPainterPath(false);
1959 		}
1960 		if (recordRegion)
1961 			regionPath.connectPath(ell);
1962 		else
1963 		{
1964 			if (recordFigure)
1965 			{
1966 				if (figClose)
1967 				{
1968 					appendPath(figurePath, ell);
1969 					figClose = false;
1970 				}
1971 				else
1972 					figurePath.connectPath(ell);
1973 			}
1974 			int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, lineWidth, CommonStrings::None, lineColor);
1975 			PageItem *ite = m_Doc->Items->at(z);
1976 			ite->PoLine = Coords.copy();
1977 			finishItem(ite);
1978 		}
1979 	//	qDebug() << "ELLIPTICAL ARC";
1980 	}
1981 	else if (elemID == 19)
1982 	{
1983 		quint16 mode;
1984 		QPointF center = getBinaryCoords(ts);
1985 		double cx = convertCoords(center.x());
1986 		double cy = convertCoords(center.y());
1987 		QPointF r1 = getBinaryCoords(ts);
1988 		double r1x = convertCoords(r1.x());
1989 		double r1y = convertCoords(r1.y());
1990 		QPointF r2 = getBinaryCoords(ts);
1991 		double r2x = convertCoords(r2.x());
1992 		double r2y = convertCoords(r2.y());
1993 		QLineF dstX = QLineF(cx, cy, r1x, r1y);
1994 		QLineF dstY = QLineF(cx, cy, r2x, r2y);
1995 		double distX = dstX.length();
1996 		double distY = dstY.length();
1997 		double rotB = dstX.angle();
1998 		double sx = convertCoords(getBinaryDistance(ts));
1999 		double sy = convertCoords(getBinaryDistance(ts));
2000 		double ex = convertCoords(getBinaryDistance(ts));
2001 		double ey = convertCoords(getBinaryDistance(ts));
2002 		ts >> mode;
2003 		if (vcdFlippedV)
2004 		{
2005 			sy *= -1;
2006 			ey *= -1;
2007 		}
2008 		if (vcdFlippedH)
2009 		{
2010 			sx *= -1;
2011 			ex *= -1;
2012 		}
2013 		QLineF stv = QLineF(cx, cy, cx + sx, cy + sy);
2014 		QLineF env = QLineF(cx, cy, cx + ex, cy + ey);
2015 		QPainterPath ell;
2016 		ell.addEllipse(QPointF(cx, cy), distX, distY);
2017 		ell.translate(-cx, -cy);
2018 		QTransform mm;
2019 		mm.rotate(rotB);
2020 		ell = mm.map(ell);
2021 		ell.translate(cx, cy);
2022 		QPolygonF elPo = ell.toFillPolygon();
2023 		QPointF stP = stv.p2();
2024 		for (int a = 0; a < elPo.size() - 1; a++)
2025 		{
2026 			QPointF intersect;
2027 			if (QLineF(elPo[a], elPo[a+1]).intersects(stv, &intersect) == QLineF::BoundedIntersection)
2028 			{
2029 				stP = intersect;
2030 				break;
2031 			}
2032 		}
2033 		QPointF enP = env.p2();
2034 		for (int a = 0; a < elPo.size() - 1; a++)
2035 		{
2036 			QPointF intersect;
2037 			if (QLineF(elPo[a], elPo[a+1]).intersects(env, &intersect) == QLineF::BoundedIntersection)
2038 			{
2039 				enP = intersect;
2040 				break;
2041 			}
2042 		}
2043 		Coords.resize(0);
2044 		Coords.svgInit();
2045 		if (mode == 0)
2046 		{
2047 			Coords.svgMoveTo(cx, cy);
2048 			if (dstX.angleTo(dstY) > 180)
2049 			{
2050 				Coords.svgLineTo(stP.x(), stP.y());
2051 				Coords.svgArcTo(distX, distY, rotB, stv.angleTo(env) < 180, dstX.angleTo(dstY) > 180, enP.x(), enP.y());
2052 			}
2053 			else
2054 			{
2055 				Coords.svgLineTo(stP.x(), stP.y());
2056 				Coords.svgArcTo(distX, distY, rotB, stv.angleTo(env) > 180, dstX.angleTo(dstY) > 180, enP.x(), enP.y());
2057 			}
2058 			Coords.svgLineTo(cx, cy);
2059 			Coords.svgClosePath();
2060 		}
2061 		else
2062 		{
2063 			if (dstX.angleTo(dstY) > 180)
2064 			{
2065 				Coords.svgMoveTo(stP.x(), stP.y());
2066 				Coords.svgArcTo(distX, distY, rotB, stv.angleTo(env) < 180, dstX.angleTo(dstY) > 180, enP.x(), enP.y());
2067 			}
2068 			else
2069 			{
2070 				Coords.svgMoveTo(stP.x(), stP.y());
2071 				Coords.svgArcTo(distX, distY, rotB, stv.angleTo(env) > 180, dstX.angleTo(dstY) > 180, enP.x(), enP.y());
2072 			}
2073 			Coords.svgLineTo(stP.x(), stP.y());
2074 			Coords.svgClosePath();
2075 		}
2076 		Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
2077 		if (recordRegion)
2078 			regionPath.addPath(Coords.toQPainterPath(false));
2079 		else
2080 		{
2081 			if (recordFigure)
2082 				figurePath.addPath(Coords.toQPainterPath(false));
2083 			PageItem *ite = itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, edgeWidth, fillColor, edgeColor);
2084 			ite->PoLine = Coords.copy();
2085 			finishItem(ite, false);
2086 		}
2087 	//	qDebug() << "ELLIPTICAL ARC CLOSE";
2088 	}
2089 	else if (elemID == 20)
2090 	{
2091 		qDebug() << "CIRCULAR ARC CENTRE REVERSED";
2092 	}
2093 	else if (elemID == 21)
2094 	{
2095 		qDebug() << "CONNECTING EDGE";
2096 	}
2097 	else if (elemID == 22)
2098 	{
2099 		qDebug() << "HYPERBOLIC ARC";
2100 	}
2101 	else if (elemID == 23)
2102 	{
2103 		qDebug() << "PARABOLIC ARC";
2104 	}
2105 	else if (elemID == 24)
2106 	{
2107 		qDebug() << "NON-UNIFORM B-SPLINE";
2108 	}
2109 	else if (elemID == 25)
2110 	{
2111 		qDebug() << "NON-UNIFORM RATIONAL B-SPLINE";
2112 	}
2113 	else if (elemID == 26)
2114 	{
2115 		getBinaryBezierPath(ts, paramLen);
2116 		if (Coords.size() > 3)
2117 		{
2118 			Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
2119 			if (recordRegion)
2120 				regionPath.addPath(Coords.toQPainterPath(false));
2121 			else
2122 			{
2123 				if (recordFigure)
2124 				{
2125 					if (figClose)
2126 					{
2127 						QPainterPath ell = Coords.toQPainterPath(false);
2128 						appendPath(figurePath, ell);
2129 						figClose = false;
2130 					}
2131 					else
2132 						figurePath.connectPath(Coords.toQPainterPath(false));
2133 				}
2134 				int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, lineWidth, CommonStrings::None, lineColor);
2135 				PageItem *ite = m_Doc->Items->at(z);
2136 				ite->PoLine = Coords.copy();
2137 				finishItem(ite);
2138 			}
2139 		}
2140 		// qDebug() << "POLYBEZIER";
2141 	}
2142 	else if (elemID == 27)
2143 	{
2144 		qDebug() << "POLYSYMBOL";
2145 	}
2146 	else if (elemID == 28)
2147 	{
2148 		uint comp = getBinaryUInt(ts, indexPrecision);
2149 		uint pad = getBinaryUInt(ts, intPrecision);
2150 		QString backColor = getBinaryColor(ts);
2151 		QString foreColor = getBinaryColor(ts);
2152 		uint prec = getBinaryUInt(ts, intPrecision);
2153 		qDebug() << "BITONAL TILE  Compression" << comp << "Padding" << pad << "Background" << backColor << "Foreground" << foreColor << "Precision" << prec;
2154 	}
2155 	else if (elemID == 29)
2156 	{
2157 		qDebug() << "TILE";
2158 	}
2159 	else
2160 	{
2161 		importRunning = false;
2162 		qDebug() << "Class 4 ID" << elemID << "Len" << paramLen;
2163 	}
2164 }
2165 
decodeClass5(QDataStream & ts,quint16 elemID,quint16 paramLen)2166 void CgmPlug::decodeClass5(QDataStream &ts, quint16 elemID, quint16 paramLen)
2167 {
2168 	if (elemID == 1)
2169 	{
2170 		lineBundleIndex = getBinaryUInt(ts, indexPrecision);
2171  		// qDebug() << "LINE BUNDLE INDEX" << lineBundleIndex;
2172 	}
2173 	else if (elemID == 2)
2174 	{
2175 		uint type = getBinaryUInt(ts, indexPrecision);
2176 		if (type == 1)
2177 			lineType = Qt::SolidLine;
2178 		else if (type == 2)
2179 			lineType = Qt::DashLine;
2180 		else if (type == 3)
2181 			lineType = Qt::DotLine;
2182 		else if (type == 4)
2183 			lineType = Qt::DashDotLine;
2184 		else if (type == 5)
2185 			lineType = Qt::DashDotDotLine;
2186 		else
2187 			lineType = Qt::SolidLine;
2188  		// qDebug() << "LINE TYPE" << lineType;
2189 	}
2190 	else if (elemID == 3)
2191 	{
2192 		lineWidth = getBinaryDistance(ts);
2193 		if (lineWidthMode == 0)
2194 			lineWidth *= metaScale;
2195 		else if (lineWidthMode == 1)
2196 			lineWidth *= 1.0;
2197 		else if (lineWidthMode == 2)
2198 			lineWidth *= 0.001;
2199 		else if (lineWidthMode == 3)
2200 			lineWidth *= 0.35;
2201 	//	if (lineWidth < 1)
2202 	//		lineWidth = 0;
2203  		// qDebug() << "LINE WIDTH" << lineWidth;
2204 	}
2205 	else if (elemID == 4)
2206 	{
2207 		lineColor = getBinaryColor(ts);
2208 		// qDebug() << "LINE COLOUR" << lineColor;
2209 	}
2210 	else if (elemID == 5)
2211 	{
2212  		qDebug() << "MARKER BUNDLE INDEX";
2213 	}
2214 	else if (elemID == 6)
2215 	{
2216  		qDebug() << "MARKER TYPE";
2217 	}
2218 	else if (elemID == 7)
2219 	{
2220  		qDebug() << "MARKER SIZE";
2221 	}
2222 	else if (elemID == 8)
2223 	{
2224  		qDebug() << "MARKER COLOUR";
2225 	}
2226 	else if (elemID == 9)
2227 	{
2228 		qDebug() << "TEXT BUNDLE INDEX";
2229 	}
2230 	else if (elemID == 10)
2231 	{
2232 		m_fontIndex = getBinaryUInt(ts, indexPrecision);
2233 	//	qDebug() << "TEXT FONT INDEX" << m_fontIndex;
2234 	}
2235 	else if (elemID == 11)
2236 	{
2237 		qDebug() << "TEXT PRECISION";
2238 	}
2239 	else if (elemID == 12)
2240 	{
2241 		qDebug() << "CHARACTER EXPANSION FACTOR";
2242 	}
2243 	else if (elemID == 13)
2244 	{
2245 		qDebug() << "CHARACTER SPACING";
2246 	}
2247 	else if (elemID == 14)
2248 	{
2249 		textColor = getBinaryColor(ts);
2250 	//	qDebug() << "TEXT COLOUR" << textColor;
2251 	}
2252 	else if (elemID == 15)
2253 	{
2254 		textSize = getBinaryDistance(ts);
2255 		textSize *= metaScale;
2256 	//	qDebug() << "CHARACTER HEIGHT" << textSize;
2257 	}
2258 	else if (elemID == 16)
2259 	{
2260 		qDebug() << "CHARACTER ORIENTATION";
2261 	}
2262 	else if (elemID == 17)
2263 	{
2264 		qDebug() << "TEXT PATH";
2265 	}
2266 	else if (elemID == 18)
2267 	{
2268 		quint16 hFlag;
2269 		ts >> hFlag;
2270 		textAlignH = hFlag;
2271 	//	qDebug() << "TEXT ALIGNMENT" << hFlag;
2272 	}
2273 	else if (elemID == 19)
2274 	{
2275 		qDebug() << "CHARACTER SET INDEX";
2276 	}
2277 	else if (elemID == 20)
2278 	{
2279 		qDebug() << "ALTERNATE CHARACTER SET INDEX";
2280 	}
2281 	else if (elemID == 21)
2282 	{
2283  		qDebug() << "FILL BUNDLE INDEX";
2284 	}
2285 	else if (elemID == 22)
2286 	{
2287 		quint16 data;
2288 		ts >> data;
2289 		fillType = data;
2290 	//	qDebug() << "INTERIOR STYLE" << fillType;
2291 	}
2292 	else if (elemID == 23)
2293 	{
2294 		fillColor = getBinaryColor(ts);
2295 	//	qDebug() << "Fill COLOUR" << fillColor;
2296 	}
2297 	else if (elemID == 24)
2298 	{
2299  		qDebug() << "HATCH INDEX";
2300 	}
2301 	else if (elemID == 25)
2302 	{
2303 		patternIndex = getBinaryUInt(ts, indexPrecision);
2304 		// Hack to fix some broken(?) CGM files
2305 		//fillType = 2;
2306 	//	qDebug() << "PATTERN INDEX" << patternIndex;
2307 	}
2308 	else if (elemID == 26)
2309 	{
2310  		qDebug() << "EDGE BUNDLE INDEX";
2311 	}
2312 	else if (elemID == 27)
2313 	{
2314 		uint type = getBinaryUInt(ts, indexPrecision);
2315 		if (type == 1)
2316 			edgeType = Qt::SolidLine;
2317 		else if (type == 2)
2318 			edgeType = Qt::DashLine;
2319 		else if (type == 3)
2320 			edgeType = Qt::DotLine;
2321 		else if (type == 4)
2322 			edgeType = Qt::DashDotLine;
2323 		else if (type == 5)
2324 			edgeType = Qt::DashDotDotLine;
2325 		else
2326 			edgeType = Qt::SolidLine;
2327  		// qDebug() << "EDGE TYPE";
2328 	}
2329 	else if (elemID == 28)
2330 	{
2331 		edgeWidth = getBinaryDistance(ts);
2332 		if (edgeWidthMode == 0)
2333 			edgeWidth *= metaScale;
2334 		else if (edgeWidthMode == 1)
2335 			edgeWidth *= 1.0;
2336 		else if (edgeWidthMode == 2)
2337 			edgeWidth *= 0.001;
2338 		else if (edgeWidthMode == 3)
2339 			edgeWidth *= 0.35;
2340 	//	if (edgeWidth < 1)
2341 	//		edgeWidth = 0;
2342  		// qDebug() << "EDGE WIDTH" << edgeWidth;
2343 	}
2344 	else if (elemID == 29)
2345 	{
2346 		edgeColor = getBinaryColor(ts);
2347 		// qDebug() << "EDGE COLOUR" << edgeColor;
2348 	}
2349 	else if (elemID == 30)
2350 	{
2351 		quint16 data;
2352 		ts >> data;
2353 		lineVisible = data != 0;
2354  		// qDebug() << "EDGE VISIBILITY";
2355 	}
2356 	else if (elemID == 31)
2357 	{
2358 		QPointF p = getBinaryCoords(ts);
2359 		double x = convertCoords(p.x());
2360 		double y = convertCoords(p.y());
2361 		fillRefPoint = QPointF(x + m_Doc->currentPage()->xOffset(), y + m_Doc->currentPage()->yOffset());
2362 	//	qDebug() << "FILL REFERENCE POINT" << fillRefPoint;
2363 	}
2364 	else if (elemID == 32)
2365 	{
2366 		uint index = getBinaryUInt(ts, indexPrecision);
2367 		uint nx = getBinaryUInt(ts, intPrecision);
2368 		uint ny = getBinaryUInt(ts, intPrecision);
2369 		int t_colorPrecision = colorPrecision;
2370 		colorPrecision = getBinaryUInt(ts, intPrecision);
2371 		QImage tmpImg = QImage(nx, ny, QImage::Format_ARGB32);
2372 		for (uint a = 0; a < ny; a++)
2373 		{
2374 			QRgb *s = (QRgb*)tmpImg.scanLine(a);
2375 			for (uint b = 0; b < nx; b++)
2376 			{
2377 				ScColor color;
2378 				if (colorMode == 0)
2379 					color = m_Doc->PageColors[getBinaryIndexedColor(ts)];
2380 				else
2381 					color = getBinaryDirectColor(ts);
2382 				QColor co = color.getRawRGBColor();
2383 				*s = qRgba(co.red(), co.green(), co.blue(), 255);
2384 				s++;
2385 			}
2386 		}
2387 		int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, 0, 0, tmpImg.width(), tmpImg.height(), 0, CommonStrings::None, CommonStrings::None);
2388 		PageItem* ite = m_Doc->Items->at(z);
2389 		ite->SetRectFrame();
2390 		ite->setTextFlowMode(PageItem::TextFlowDisabled);
2391 		m_Doc->adjustItemSize(ite);
2392 		ite->OldB2 = ite->width();
2393 		ite->OldH2 = ite->height();
2394 		QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_cgm_XXXXXX.png");
2395 		tempFile->setAutoRemove(false);
2396 		if (tempFile->open())
2397 		{
2398 			QString fileName = getLongPathName(tempFile->fileName());
2399 			if (!fileName.isEmpty())
2400 			{
2401 				tempFile->close();
2402 				ite->isInlineImage = true;
2403 				ite->isTempFile = true;
2404 				tmpImg.save(fileName, "PNG");
2405 				m_Doc->loadPict(fileName, ite);
2406 				ite->setImageScalingMode(false, true);
2407 				ScPattern pat = ScPattern();
2408 				pat.setDoc(m_Doc);
2409 				pat.pattern = tmpImg;
2410 				pat.xoffset = 0;
2411 				pat.yoffset = 0;
2412 				pat.width = ite->width();
2413 				pat.height = ite->height();
2414 				ite->gXpos = 0;
2415 				ite->gYpos = 0;
2416 				ite->setXYPos(ite->gXpos, ite->gYpos, true);
2417 				pat.items.append(ite);
2418 				m_Doc->Items->removeAll(ite);
2419 				QString id = QString("Pattern_from_CGM_%1").arg(m_Doc->docPatterns.count() + 1);
2420 				m_Doc->addPattern(id, pat);
2421 				patternTable.insert(index, id);
2422 			}
2423 			else
2424 			{
2425 				m_Doc->Items->removeAll(ite);
2426 				delete ite;
2427 			}
2428 		}
2429 		else
2430 		{
2431 			m_Doc->Items->removeAll(ite);
2432 			delete ite;
2433 		}
2434 		delete tempFile;
2435 		colorPrecision = t_colorPrecision;
2436 	//	qDebug() << "PATTERN TABLE" << "Index" << index << "NX" << nx << "NY" << ny;
2437 	}
2438 	else if (elemID == 33)
2439 	{
2440 		double phx = convertCoords(getBinaryDistance(ts));
2441 		double phy = convertCoords(getBinaryDistance(ts));
2442 		double pwx = convertCoords(getBinaryDistance(ts));
2443 		double pwy = convertCoords(getBinaryDistance(ts));
2444 		QLineF hp = QLineF(0, 0, phx, phy);
2445 		QLineF wp = QLineF(0, 0, pwx, pwy);
2446 		patternScaleX = wp.length();
2447 		patternScaleY = hp.length();
2448 	//	qDebug() << "PATTERN SIZE" << wp.length() << hp.length();
2449 	}
2450 	else if (elemID == 34)
2451 	{
2452 //		qDebug() << "COLOUR TABLE" << "Starting at" << ts.device()->pos();
2453 		getBinaryColorTable(ts, paramLen);
2454 	}
2455 	else if (elemID == 35)
2456 	{
2457 		qDebug() << "ASPECT SOURCE FLAGS";
2458 	}
2459 	else if (elemID == 36)
2460 	{
2461 		qDebug() << "PICK IDENTIFIER";
2462 	}
2463 	else if (elemID == 37)
2464 	{
2465 		uint type = getBinaryUInt(ts, indexPrecision);
2466 		if (type == 1)
2467 			lineCap = Qt::FlatCap;
2468 		else if (type == 2)
2469 			lineCap = Qt::RoundCap;
2470 		else if (type == 3)
2471 			lineCap = Qt::SquareCap;
2472 		else
2473 			lineCap = Qt::FlatCap;
2474 		type = getBinaryUInt(ts, indexPrecision);		// dummy reading unsupported parameter
2475 		// qDebug() << "LINE CAP";
2476 	}
2477 	else if (elemID == 38)
2478 	{
2479 		uint type = getBinaryUInt(ts, indexPrecision);
2480 		if (type == 1)
2481 			lineJoin = Qt::MiterJoin;
2482 		else if (type == 2)
2483 			lineJoin = Qt::RoundJoin;
2484 		else if (type == 3)
2485 			lineJoin = Qt::BevelJoin;
2486 		else
2487 			lineJoin = Qt::MiterJoin;
2488 		// qDebug() << "LINE JOIN";
2489 	}
2490 	else if (elemID == 39)
2491 	{
2492 		qDebug() << "LINE TYPE CONTINUATION";
2493 	}
2494 	else if (elemID == 40)
2495 	{
2496 		qDebug() << "LINE TYPE INITIAL OFFSET";
2497 	}
2498 	else if (elemID == 41)
2499 	{
2500 		qDebug() << "TEXT SCORE TYPE";
2501 	}
2502 	else if (elemID == 42)
2503 	{
2504 		textScaleMode = getBinaryUInt(ts, indexPrecision);
2505 		qDebug() << "RESTRICTED TEXT TYPE" << textScaleMode;
2506 	}
2507 	else if (elemID == 43)
2508 	{
2509 		int posI = ts.device()->pos();
2510 		uint type = getBinaryUInt(ts, indexPrecision);
2511 		QPointF p1 = convertCoords(getBinaryCoords(ts));
2512 		QPointF p2 = convertCoords(getBinaryCoords(ts));
2513 		uint index = getBinaryUInt(ts, intPrecision);
2514 	//	qDebug() << "INTERPOLATED INTERIOR  Type" << type << "from" << p1 << "to" << p2 << "Stages" << index << "at" << posI << realPrecision << realMantissa;
2515 		for (uint s = 0; s < index; s++)
2516 		{
2517 			double s1 = getBinaryReal(ts, realPrecision, realMantissa);
2518 			qDebug() << "Stages " << s1;
2519 		}
2520 		Q_UNUSED(posI);
2521 		Q_UNUSED(type);
2522 		Q_UNUSED(p1);
2523 		Q_UNUSED(p2);
2524 /*		int pos = ts.device()->pos();
2525 		uint type = getBinaryUInt(ts, indexPrecision);
2526 		QPointF p, p2;
2527 		if (type == 1)
2528 		{
2529 			int posE = ts.device()->pos();
2530 			p = QPointF(convertCoords(getBinaryDistance(ts)), convertCoords(getBinaryDistance(ts)));
2531 			qDebug() << "End Point" << p << " at" << posE;
2532 		}
2533 		else if (type == 2)
2534 		{
2535 			int posE = ts.device()->pos();
2536 			p = QPointF(convertCoords(getBinaryDistance(ts)), convertCoords(getBinaryDistance(ts)));
2537 			p2 = QPointF(convertCoords(getBinaryDistance(ts)), convertCoords(getBinaryDistance(ts)));
2538 			qDebug() << "Points" << p << p2 << " at" << posE;
2539 		}
2540 		int posI = ts.device()->pos();
2541 		uint index = getBinaryUInt(ts, intPrecision);
2542 		qDebug() << "Stages " << index << " at" << posI;
2543 		for (uint s = 0; s < index; s++)
2544 		{
2545 			double s1 = getBinaryReal(ts, realPrecision, realMantissa);
2546 			qDebug() << "first 2 Stages " << s1;
2547 		}
2548 		ts.device()->seek(pos); */
2549 	//	qDebug() << "INTERPOLATED INTERIOR  Type" << type << "from" << p1 << "to" << p2 << "Stages" << index << "at" << posI;
2550 	}
2551 	else if (elemID == 44)
2552 	{
2553 		uint type = getBinaryUInt(ts, indexPrecision);
2554 		if (type == 1)
2555 			edgeCap = Qt::FlatCap;
2556 		else if (type == 2)
2557 			edgeCap = Qt::RoundCap;
2558 		else if (type == 3)
2559 			edgeCap = Qt::SquareCap;
2560 		else
2561 			edgeCap = Qt::FlatCap;
2562 		type = getBinaryUInt(ts, indexPrecision);		// dummy reading unsupported parameter
2563  		// qDebug() << "EDGE CAP";
2564 	}
2565 	else if (elemID == 45)
2566 	{
2567 		uint type = getBinaryUInt(ts, indexPrecision);
2568 		if (type == 1)
2569 			edgeJoin = Qt::MiterJoin;
2570 		else if (type == 2)
2571 			edgeJoin = Qt::RoundJoin;
2572 		else if (type == 3)
2573 			edgeJoin = Qt::BevelJoin;
2574 		else
2575 			edgeJoin = Qt::MiterJoin;
2576 		// qDebug() << "EDGE JOIN";
2577 	}
2578 	else if (elemID == 46)
2579 	{
2580 		qDebug() << "EDGE TYPE CONTINUATION";
2581 	}
2582 	else if (elemID == 47)
2583 	{
2584 		qDebug() << "EDGE TYPE INITIAL OFFSET";
2585 	}
2586 	else if (elemID == 48)
2587 	{
2588 		qDebug() << "SYMBOL LIBRARY INDEX";
2589 	}
2590 	else if (elemID == 49)
2591 	{
2592 		qDebug() << "SYMBOL COLOUR";
2593 	}
2594 	else if (elemID == 50)
2595 	{
2596 		qDebug() << "SYMBOL SIZE";
2597 	}
2598 	else if (elemID == 51)
2599 	{
2600 		qDebug() << "SYMBOL ORIENTATION";
2601 	}
2602 	else
2603 	{
2604 		importRunning = false;
2605 		qDebug() << "Class 5 ID" << elemID << "Len" << paramLen;
2606 	}
2607 }
2608 
decodeClass6(QDataStream & ts,quint16 elemID,quint16 paramLen)2609 void CgmPlug::decodeClass6(QDataStream &ts, quint16 elemID, quint16 paramLen)
2610 {
2611 	if (elemID == 1)
2612 	{
2613 		qDebug() << "ESCAPE";
2614 	}
2615 	else
2616 	{
2617 		importRunning = false;
2618 		qDebug() << "Class 6 ID" << elemID << "Len" << paramLen;
2619 	}
2620 }
2621 
decodeClass7(QDataStream & ts,quint16 elemID,quint16 paramLen)2622 void CgmPlug::decodeClass7(QDataStream &ts, quint16 elemID, quint16 paramLen)
2623 {
2624 	if (elemID == 1)
2625 	{
2626 		qDebug() << "MESSAGE";
2627 	}
2628 	else if (elemID == 2)
2629 	{
2630 		qDebug() << "APPLICATION DATA" << paramLen << "at" << ts.device()->pos();
2631 	}
2632 	else
2633 	{
2634 		importRunning = false;
2635 		qDebug() << "Class 7 ID" << elemID << "Len" << paramLen;
2636 	}
2637 }
2638 
decodeClass8(QDataStream & ts,quint16 elemID,quint16 paramLen)2639 void CgmPlug::decodeClass8(QDataStream &ts, quint16 elemID, quint16 paramLen)
2640 {
2641 	if (elemID == 1)
2642 	{
2643 		qDebug() << "COPY SEGMENT";
2644 	}
2645 	else if (elemID == 2)
2646 	{
2647 		qDebug() << "INHERITANCE FILTER";
2648 	}
2649 	else if (elemID == 3)
2650 	{
2651 		qDebug() << "CLIP INHERITANCE";
2652 	}
2653 	else if (elemID == 4)
2654 	{
2655 		qDebug() << "SEGMENT TRANSFORMATION";
2656 	}
2657 	else if (elemID == 5)
2658 	{
2659 		qDebug() << "SEGMENT HIGHLIGHTING";
2660 	}
2661 	else if (elemID == 6)
2662 	{
2663 		qDebug() << "SEGMENT DISPLAY PRIORITY";
2664 	}
2665 	else if (elemID == 7)
2666 	{
2667 		qDebug() << "SEGMENT PICK PRIORITY";
2668 	}
2669 	else
2670 	{
2671 		importRunning = false;
2672 		qDebug() << "Class 8 ID" << elemID << "Len" << paramLen;
2673 	}
2674 }
2675 
decodeClass9(QDataStream & ts,quint16 elemID,quint16 paramLen)2676 void CgmPlug::decodeClass9(QDataStream &ts, quint16 elemID, quint16 paramLen)
2677 {
2678 	if (elemID == 1)
2679 	{
2680 		qDebug() << "APPLICATION STRUCTURE ATTRIBUTE";
2681 	}
2682 	else
2683 	{
2684 		importRunning = false;
2685 		qDebug() << "Class 9 ID" << elemID << "Len" << paramLen;
2686 	}
2687 }
2688 
getBinaryBezierPath(QDataStream & ts,quint16 paramLen)2689 void CgmPlug::getBinaryBezierPath(QDataStream &ts, quint16 paramLen)
2690 {
2691 	quint16 bytesRead = 0;
2692 	bool first = true;
2693 	Coords.resize(0);
2694 	Coords.svgInit();
2695 	quint16 flag;
2696 	flag = paramLen & 0x8000;
2697 	paramLen = paramLen & 0x7FFF;
2698 	uint type = getBinaryUInt(ts, indexPrecision);
2699 	while (bytesRead < paramLen - 2)
2700 	{
2701 		int posA = ts.device()->pos();
2702 		if ((first) || (type == 1))
2703 		{
2704 			QPointF p = getBinaryCoords(ts);
2705 			Coords.svgMoveTo(convertCoords(p.x()), convertCoords(p.y()));
2706 			first = false;
2707 		}
2708 		QPointF p1 = getBinaryCoords(ts);
2709 		QPointF p2 = getBinaryCoords(ts);
2710 		QPointF p3 = getBinaryCoords(ts);
2711 		Coords.svgCurveToCubic(convertCoords(p1.x()), convertCoords(p1.y()), convertCoords(p2.x()), convertCoords(p2.y()), convertCoords(p3.x()), convertCoords(p3.y()));
2712 		int posN = ts.device()->pos();
2713 		bytesRead += posN - posA;
2714 	}
2715 	while (flag)
2716 	{
2717 		bytesRead = 0;
2718 		ts >> paramLen;
2719 		flag = paramLen & 0x8000;
2720 		paramLen = paramLen & 0x7FFF;
2721 		while (bytesRead < paramLen)
2722 		{
2723 			int posA = ts.device()->pos();
2724 			if (type == 1)
2725 			{
2726 				QPointF p = getBinaryCoords(ts);
2727 				Coords.svgMoveTo(convertCoords(p.x()), convertCoords(p.y()));
2728 			}
2729 			QPointF p1 = getBinaryCoords(ts);
2730 			QPointF p2 = getBinaryCoords(ts);
2731 			QPointF p3 = getBinaryCoords(ts);
2732 			Coords.svgCurveToCubic(convertCoords(p1.x()), convertCoords(p1.y()), convertCoords(p2.x()), convertCoords(p2.y()), convertCoords(p3.x()), convertCoords(p3.y()));
2733 			int posN = ts.device()->pos();
2734 			bytesRead += posN - posA;
2735 		}
2736 	}
2737 }
2738 
getBinaryPath(QDataStream & ts,quint16 paramLen,bool disjoint)2739 void CgmPlug::getBinaryPath(QDataStream &ts, quint16 paramLen, bool disjoint)
2740 {
2741 	quint16 bytesRead = 0;
2742 	bool first = true;
2743 	Coords.resize(0);
2744 	Coords.svgInit();
2745 	quint16 flag;
2746 	flag = paramLen & 0x8000;
2747 	paramLen = paramLen & 0x7FFF;
2748 	while (bytesRead < paramLen)
2749 	{
2750 		int posA = ts.device()->pos();
2751 		QPointF p = getBinaryCoords(ts);
2752 		if (first)
2753 		{
2754 			Coords.svgMoveTo(convertCoords(p.x()), convertCoords(p.y()));
2755 			first = false;
2756 		}
2757 		else
2758 		{
2759 			Coords.svgLineTo(convertCoords(p.x()), convertCoords(p.y()));
2760 			if (disjoint)
2761 				first = true;
2762 		}
2763 		int posN = ts.device()->pos();
2764 		bytesRead += posN - posA;
2765 	}
2766 	while (flag)
2767 	{
2768 		bytesRead = 0;
2769 		ts >> paramLen;
2770 		flag = paramLen & 0x8000;
2771 		paramLen = paramLen & 0x7FFF;
2772 		while (bytesRead < paramLen)
2773 		{
2774 			int posA = ts.device()->pos();
2775 			if (disjoint)
2776 			{
2777 				QPointF p = getBinaryCoords(ts);
2778 				if (first)
2779 				{
2780 					Coords.svgMoveTo(convertCoords(p.x()), convertCoords(p.y()));
2781 					first = false;
2782 				}
2783 				else
2784 				{
2785 					Coords.svgLineTo(convertCoords(p.x()), convertCoords(p.y()));
2786 					if (disjoint)
2787 						first = true;
2788 				}
2789 			}
2790 			else
2791 			{
2792 				QPointF p = getBinaryCoords(ts);
2793 				Coords.svgLineTo(convertCoords(p.x()), convertCoords(p.y()));
2794 			}
2795 			int posN = ts.device()->pos();
2796 			bytesRead += posN - posA;
2797 		}
2798 	}
2799 }
2800 
getBinaryColorTable(QDataStream & ts,quint16 paramLen)2801 void CgmPlug::getBinaryColorTable(QDataStream &ts, quint16 paramLen)
2802 {
2803 	quint16 flag;
2804 	flag = paramLen & 0x8000;
2805 	paramLen = paramLen & 0x7FFF;
2806 	quint16 bytesRead = 0;
2807 	int posA = ts.device()->pos();
2808 	uint c = getBinaryUInt(ts, colorIndexPrecision);
2809 	int posN = ts.device()->pos();
2810 	bytesRead += posN - posA;
2811 	QString tmpName = CommonStrings::None;
2812 	while (bytesRead < paramLen)
2813 	{
2814 		posA = ts.device()->pos();
2815 		ScColor cc = getBinaryDirectColor(ts);
2816 		tmpName = handleColor(cc, "FromCGM"+cc.name());
2817 		ColorTableMap.insert(c, tmpName);
2818 		c++;
2819 		posN = ts.device()->pos();
2820 		bytesRead += posN - posA;
2821 	}
2822 	while (flag)
2823 	{
2824 		bytesRead = 0;
2825 		ts >> paramLen;
2826 		flag = paramLen & 0x8000;
2827 		paramLen = paramLen & 0x7FFF;
2828 		while (bytesRead < paramLen)
2829 		{
2830 			posA = ts.device()->pos();
2831 			//ScColor cc = getBinaryDirectColor(ts);
2832 			ColorTableMap.insert(c, tmpName);
2833 			c++;
2834 			posN = ts.device()->pos();
2835 			bytesRead += posN - posA;
2836 		}
2837 	}
2838 }
2839 
getBinaryDirectColor(ScBitReader * breader)2840 ScColor CgmPlug::getBinaryDirectColor(ScBitReader *breader)
2841 {
2842 	ScColor ret;
2843 	if (m_colorModel == 1)		// RGB
2844 	{
2845 		int r = breader->getUInt(colorPrecision);
2846 		int g = breader->getUInt(colorPrecision);
2847 		int b = breader->getUInt(colorPrecision);
2848 		r = qRound(r * (maxColor - minColor) / static_cast<double>(maxColor));
2849 		g = qRound(g * (maxColor - minColor) / static_cast<double>(maxColor));
2850 		b = qRound(b * (maxColor - minColor) / static_cast<double>(maxColor));
2851 		ret = ScColor(r, g, b);
2852 	}
2853 	else if (m_colorModel == 4)	// CMYK
2854 	{
2855 		uint c = breader->getUInt(colorPrecision);
2856 		uint m = breader->getUInt(colorPrecision);
2857 		uint y = breader->getUInt(colorPrecision);
2858 		uint k = breader->getUInt(colorPrecision);
2859 		c = qRound(c * (maxColor - minColor) / static_cast<double>(maxColor));
2860 		m = qRound(m * (maxColor - minColor) / static_cast<double>(maxColor));
2861 		y = qRound(y * (maxColor - minColor) / static_cast<double>(maxColor));
2862 		k = qRound(k * (maxColor - minColor) / static_cast<double>(maxColor));
2863 		ret = ScColor(c, m, y, k);
2864 	}
2865 	return ret;
2866 }
2867 
getBinaryDirectColor(QDataStream & ts)2868 ScColor CgmPlug::getBinaryDirectColor(QDataStream &ts)
2869 {
2870 	ScColor ret;
2871 	if (m_colorModel == 1)		// RGB
2872 	{
2873 		if (colorPrecision == 8)
2874 		{
2875 			quint8 ri, gi, bi;
2876 			ts >> ri >> gi >> bi;
2877 			int r = ri;
2878 			int g = gi;
2879 			int b = bi;
2880 			r = qRound(r * (maxColor - minColor) / static_cast<double>(maxColor));
2881 			g = qRound(g * (maxColor - minColor) / static_cast<double>(maxColor));
2882 			b = qRound(b * (maxColor - minColor) / static_cast<double>(maxColor));
2883 			ret = ScColor(r, g, b);
2884 		}
2885 		else if (colorPrecision == 16)
2886 		{
2887 			quint16 ri, gi, bi;
2888 			ts >> ri >> gi >> bi;
2889 			int r = ri;
2890 			int g = gi;
2891 			int b = bi;
2892 			r = qRound((r * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2893 			g = qRound((g * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2894 			b = qRound((b * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2895 			ret = ScColor(r, g, b);
2896 		}
2897 		else if (colorPrecision == 24)
2898 		{
2899 			quint8  p1;
2900 			quint16 p2;
2901 			quint32 ri = 0;
2902 			quint32 gi = 0;
2903 			quint32 bi = 0;
2904 			ts >> p2;
2905 			ts >> p1;
2906 			ri = p2 << 8;
2907 			ri |= p1;
2908 			ts >> p2;
2909 			ts >> p1;
2910 			gi = p2 << 8;
2911 			gi |= p1;
2912 			ts >> p2;
2913 			ts >> p1;
2914 			bi = p2 << 8;
2915 			bi |= p1;
2916 			int r = ri;
2917 			int g = gi;
2918 			int b = bi;
2919 			r = qRound((r * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2920 			g = qRound((g * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2921 			b = qRound((b * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2922 			ret = ScColor(r, g, b);
2923 		}
2924 		else if (colorPrecision == 32)
2925 		{
2926 			quint32 ri, gi, bi;
2927 			ts >> ri >> gi >> bi;
2928 			int r = ri;
2929 			int g = gi;
2930 			int b = bi;
2931 			r = qRound((r * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2932 			g = qRound((g * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2933 			b = qRound((b * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2934 			ret = ScColor(r, g, b);
2935 		}
2936 	}
2937 	else if (m_colorModel == 4)	// CMYK
2938 	{
2939 		if (colorPrecision == 8)
2940 		{
2941 			quint8 ci, mi, yi, ki;
2942 			ts >> ci >> mi >> yi >> ki;
2943 			uint c = ci;
2944 			uint m = mi;
2945 			uint y = yi;
2946 			uint k = ki;
2947 			c = qRound(c * (maxColor - minColor) / static_cast<double>(maxColor));
2948 			m = qRound(m * (maxColor - minColor) / static_cast<double>(maxColor));
2949 			y = qRound(y * (maxColor - minColor) / static_cast<double>(maxColor));
2950 			k = qRound(k * (maxColor - minColor) / static_cast<double>(maxColor));
2951 			ret = ScColor(c, m, y, k);
2952 		}
2953 		else if (colorPrecision == 16)
2954 		{
2955 			quint16 ci, mi, yi, ki;
2956 			ts >> ci >> mi >> yi >> ki;
2957 			uint c = ci;
2958 			uint m = mi;
2959 			uint y = yi;
2960 			uint k = ki;
2961 			c = qRound((c * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2962 			m = qRound((m * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2963 			y = qRound((y * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2964 			k = qRound((k * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2965 			ret = ScColor(c, m, y, k);
2966 		}
2967 		else if (colorPrecision == 24)
2968 		{
2969 			quint8  p1;
2970 			quint16 p2;
2971 			quint32 ci = 0;
2972 			ts >> p2;
2973 			ts >> p1;
2974 			ci = p2 << 8;
2975 			ci |= p1;
2976 			quint32 mi = 0;
2977 			ts >> p2;
2978 			ts >> p1;
2979 			mi = p2 << 8;
2980 			mi |= p1;
2981 			quint32 yi = 0;
2982 			ts >> p2;
2983 			ts >> p1;
2984 			yi = p2 << 8;
2985 			yi |= p1;
2986 			quint32 ki = 0;
2987 			ts >> p2;
2988 			ts >> p1;
2989 			ki = p2 << 8;
2990 			ki |= p1;
2991 			uint c = ci;
2992 			uint m = mi;
2993 			uint y = yi;
2994 			uint k = ki;
2995 			c = qRound((c * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2996 			m = qRound((m * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2997 			y = qRound((y * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2998 			k = qRound((k * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
2999 			ret = ScColor(c, m, y, k);
3000 		}
3001 		else if (colorPrecision == 32)
3002 		{
3003 			quint32 ci, mi, yi, ki;
3004 			ts >> ci >> mi >> yi >> ki;
3005 			uint c = ci;
3006 			uint m = mi;
3007 			uint y = yi;
3008 			uint k = ki;
3009 			c = qRound((c * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
3010 			m = qRound((m * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
3011 			y = qRound((y * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
3012 			k = qRound((k * (maxColor - minColor) / static_cast<double>(maxColor)) / static_cast<double>(maxColor) * 255.0);
3013 			ret = ScColor(c, m, y, k);
3014 		}
3015 	}
3016 	return ret;
3017 }
3018 
getBinaryIndexedColor(ScBitReader * breader)3019 QString CgmPlug::getBinaryIndexedColor(ScBitReader *breader)
3020 {
3021 	QString ret = "Black";
3022 	uint c = breader->getUInt(colorIndexPrecision);
3023 	if (ColorTableMap.contains(c) && (c <= maxColorIndex))
3024 		ret = ColorTableMap[c];
3025 	return ret;
3026 }
3027 
getBinaryIndexedColor(QDataStream & ts)3028 QString CgmPlug::getBinaryIndexedColor(QDataStream &ts)
3029 {
3030 	QString ret = "Black";
3031 	uint c = getBinaryUInt(ts, colorIndexPrecision);
3032 	if (ColorTableMap.contains(c) && (c <= maxColorIndex))
3033 		ret = ColorTableMap[c];
3034 	return ret;
3035 }
3036 
getBinaryColor(QDataStream & ts)3037 QString CgmPlug::getBinaryColor(QDataStream &ts)
3038 {
3039 	QString ret;
3040 	ScColor color;
3041 	if (colorMode == 0)
3042 	{
3043 		ret = getBinaryIndexedColor(ts);
3044 	}
3045 	else
3046 	{
3047 		color = getBinaryDirectColor(ts);
3048 		ret = handleColor(color, "FromCGM"+color.name());
3049 	}
3050 	return ret;
3051 }
3052 
getBinaryDistance(QDataStream & ts)3053 double CgmPlug::getBinaryDistance(QDataStream &ts)
3054 {
3055 	double ret = 0.0;
3056 	if (vdcType == 0)				// integer coords
3057 	{
3058 		int x = getBinaryInt(ts, vdcInt);
3059 		ret = x;
3060 	}
3061 	else
3062 		ret = getBinaryReal(ts, vdcReal, vdcMantissa);
3063 	return ret;
3064 }
3065 
getBinaryCoords(QDataStream & ts,bool raw)3066 QPointF CgmPlug::getBinaryCoords(QDataStream &ts, bool raw)
3067 {
3068 	QPointF ret = QPointF(0.0, 0.0);
3069 	if (vdcType == 0)				// integer coords
3070 	{
3071 		int x = getBinaryInt(ts, vdcInt);
3072 		int y = getBinaryInt(ts, vdcInt);
3073 		if (!raw)
3074 		{
3075 			if (vcdFlippedV)
3076 				y = vdcHeight - y;
3077 			if (vcdFlippedH)
3078 				x = vdcWidth - x;
3079 		}
3080 		ret = QPointF(x, y);
3081 	}
3082 	else
3083 	{
3084 		double x = getBinaryReal(ts, vdcReal, vdcMantissa);
3085 		double y = getBinaryReal(ts, vdcReal, vdcMantissa);
3086 		if (!raw)
3087 		{
3088 			if (vcdFlippedV)
3089 				y = vdcHeight - y;
3090 			if (vcdFlippedH)
3091 				x = vdcWidth - x;
3092 		}
3093 		ret = QPointF(x, y);
3094 	}
3095 	return ret;
3096 }
3097 
getBinaryUInt(QDataStream & ts,int intP)3098 uint CgmPlug::getBinaryUInt(QDataStream &ts, int intP)
3099 {
3100 	uint val = 0;
3101 	if (intP == 1)
3102 	{
3103 		quint8 data;
3104 		ts >> data;
3105 		val = data >> 7;
3106 	}
3107 	else if (intP == 8)
3108 	{
3109 		quint8 data;
3110 		ts >> data;
3111 		val = data;
3112 	}
3113 	else if (intP == 16)
3114 	{
3115 		quint16 data;
3116 		ts >> data;
3117 		val = data;
3118 	}
3119 	else if (intP == 24)
3120 	{
3121 		quint8  p1;
3122 		quint16 p2;
3123 		quint32 data = 0;
3124 		ts >> p2;
3125 		ts >> p1;
3126 		data = p2 << 8;
3127 		data |= p1;
3128 		val = data;
3129 	}
3130 	else if (intP == 32)
3131 	{
3132 		quint32 data;
3133 		ts >> data;
3134 		val = data;
3135 	}
3136 	return val;
3137 }
3138 
getBinaryInt(QDataStream & ts,int intP)3139 int CgmPlug::getBinaryInt(QDataStream &ts, int intP)
3140 {
3141 	int val = 0;
3142 	if (intP == 8)
3143 	{
3144 		qint8 data;
3145 		ts >> data;
3146 		val = data;
3147 	}
3148 	else if (intP == 16)
3149 	{
3150 		qint16 data;
3151 		ts >> data;
3152 		val = data;
3153 	}
3154 	else if (intP == 24)
3155 	{
3156 		qint8  p1;
3157 		qint16 p2;
3158 		qint32 data = 0;
3159 		ts >> p2;
3160 		ts >> p1;
3161 		data = p2 << 8;
3162 		data |= p1;
3163 		val = data;
3164 	}
3165 	else if (intP == 32)
3166 	{
3167 		qint32 data;
3168 		ts >> data;
3169 		val = data;
3170 	}
3171 	return val;
3172 }
3173 
getBinaryReal(QDataStream & ts,int realP,int realM)3174 double CgmPlug::getBinaryReal(QDataStream &ts, int realP, int realM)
3175 {
3176 	double val = 0.0;
3177 	if (realP == 0)			// real Format
3178 	{
3179 		if (realM == 9)		// 32bit
3180 		{
3181 			ts.setFloatingPointPrecision(QDataStream::SinglePrecision);
3182 			float data;
3183 			ts >> data;
3184 			val = data;
3185 		}
3186 		else
3187 		{
3188 			ts.setFloatingPointPrecision(QDataStream::DoublePrecision);
3189 			double data;
3190 			ts >> data;
3191 			val = data;
3192 		}
3193 	}
3194 	else							// fixed Point Format
3195 	{
3196 		if (realM == 16)	// 32bit
3197 		{
3198 			quint16 fraction;
3199 			qint16 whole;
3200 			ts >> whole;
3201 			ts >> fraction;
3202 			int gpart = whole;
3203 			val = gpart + (fraction / static_cast<double>(0xFFFF));
3204 /*			quint16 flag = whole & 0x8000;
3205 			whole = whole & 0x7FFF;
3206 			if (flag)
3207 				val = whole - (fraction / static_cast<double>(0xFFFF));
3208 			else
3209 				val = whole + (fraction / static_cast<double>(0xFFFF)); */
3210 		}
3211 		else
3212 		{
3213 			quint32 fraction;
3214 			qint32 whole;
3215 			ts >> whole;
3216 			ts >> fraction;
3217 			int gpart = whole;
3218 			val = gpart + (fraction / static_cast<double>(0xFFFFFFFF));
3219 /*			quint32 flag = whole & 0x80000000;
3220 			whole = whole & 0x7FFFFFFF;
3221 			if (flag)
3222 				val = whole - (fraction / static_cast<double>(0xFFFFFFFF));
3223 			else
3224 				val = whole + (fraction / static_cast<double>(0xFFFFFFFF)); */
3225 		}
3226 	}
3227 	return val;
3228 }
3229 
getBinaryText(QDataStream & ts)3230 QString CgmPlug::getBinaryText(QDataStream &ts)
3231 {
3232 	quint8 textLen;
3233 	QByteArray text;
3234 	ts >> textLen;
3235 	if (textLen == 0)
3236 		ts >> textLen;
3237 	if (textLen < 255)
3238 	{
3239 		text.resize(textLen);
3240 		ts.readRawData(text.data(), textLen);
3241 	}
3242 	else
3243 	{
3244 		quint16 extTextLen;
3245 		quint16 flag;
3246 		QByteArray textE;
3247 		ts >> extTextLen;
3248 		flag = extTextLen & 0x8000;
3249 		extTextLen = extTextLen & 0x7FFF;
3250 		textE.resize(extTextLen);
3251 		ts.readRawData(textE.data(), extTextLen);
3252 		alignStreamToWord(ts, 0);
3253 		text += textE;
3254 		while (flag)
3255 		{
3256 			ts >> extTextLen;
3257 			flag = extTextLen & 0x8000;
3258 			extTextLen = extTextLen & 0x7FFF;
3259 			textE.resize(extTextLen);
3260 			ts.readRawData(textE.data(), extTextLen);
3261 			text += textE;
3262 		}
3263 	}
3264 	return text;
3265 }
3266 
alignStreamToWord(QDataStream & ts,uint len)3267 void CgmPlug::alignStreamToWord(QDataStream &ts, uint len)
3268 {
3269 	quint16 flag;
3270 	flag = len & 0x8000;
3271 	quint16 paramLen = len & 0x7FFF;
3272 	ts.skipRawData(paramLen);
3273 	while (flag)
3274 	{
3275 		ts >> paramLen;
3276 		flag = paramLen & 0x8000;
3277 		paramLen = paramLen & 0x7FFF;
3278 		ts.skipRawData(paramLen);
3279 	}
3280 	uint adj = ts.device()->pos() % 2;
3281 	if (adj != 0)
3282 		ts.skipRawData(1);
3283 }
3284 /* End binary Decoder */
3285 
3286 /* Start of core Functions common to both Decoders */
3287 
handleStartMetaFile(const QString & value)3288 void CgmPlug::handleStartMetaFile(const QString& value)
3289 {
3290 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
3291 		m_Doc->documentInfo().setTitle(value);
3292 	// qDebug() << "Start Metafile" << value;
3293 }
3294 
handleStartPicture(const QString & value)3295 void CgmPlug::handleStartPicture(const QString& value)
3296 {
3297 	pictName = value;
3298 //	qDebug() << "Start Picture" << value;
3299 }
3300 
handleStartPictureBody(double width,double height)3301 void CgmPlug::handleStartPictureBody(double width, double height)
3302 {
3303 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
3304 	{
3305 		if (firstPage)
3306 		{
3307 			m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
3308 			if (width > height)
3309 				m_Doc->setPageOrientation(1);
3310 			else
3311 				m_Doc->setPageOrientation(0);
3312 			m_Doc->setPageSize("Custom");
3313 			m_Doc->changePageProperties(0, 0, 0, 0, height, width, height, width, m_Doc->pageOrientation(), m_Doc->pageSize(), m_Doc->currentPage()->pageNr(), false);
3314 		}
3315 		else
3316 		{
3317 			if (wasEndPic)
3318 			{
3319 				m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
3320 				m_Doc->addPage(m_Doc->currentPage()->pageNr()+1);
3321 				m_Doc->view()->addPage(m_Doc->currentPage()->pageNr(), true);
3322 			}
3323 		}
3324 		wasEndPic = false;
3325 		firstPage = false;
3326 	}
3327 }
3328 
handleMetaFileDescription(const QString & value)3329 void CgmPlug::handleMetaFileDescription(const QString& value)
3330 {
3331 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
3332 		m_Doc->documentInfo().setComments(value);
3333 	// qDebug() << "Metafile Description" << value;
3334 }
3335 
handleColor(ScColor & color,const QString & proposedName)3336 QString CgmPlug::handleColor(ScColor &color, const QString& proposedName)
3337 {
3338 	QString tmpName = m_Doc->PageColors.tryAddColor(proposedName, color);
3339 	if (tmpName == proposedName)
3340 		importedColors.append(tmpName);
3341 	return tmpName;
3342 }
3343 
convertCoords(double input)3344 double CgmPlug::convertCoords(double input)
3345 {
3346 	return input * metaScale;
3347 }
3348 
convertCoords(QPointF input)3349 QPointF CgmPlug::convertCoords(QPointF input)
3350 {
3351 	return input * metaScale;
3352 }
3353 
appendPath(QPainterPath & path1,QPainterPath & path2)3354 void CgmPlug::appendPath(QPainterPath &path1, QPainterPath &path2)
3355 {
3356 	for (int i = 0; i < path2.elementCount(); ++i)
3357 	{
3358 		const QPainterPath::Element &elm = path2.elementAt(i);
3359 		switch (elm.type)
3360 		{
3361 			case QPainterPath::MoveToElement:
3362 				path1.moveTo(elm.x, elm.y);
3363 				break;
3364 			case QPainterPath::LineToElement:
3365 				path1.lineTo(elm.x, elm.y);
3366 				break;
3367 			case QPainterPath::CurveToElement:
3368 				path1.cubicTo(elm.x, elm.y, path2.elementAt(i+1).x, path2.elementAt(i+1).y, path2.elementAt(i+2).x, path2.elementAt(i+2).y );
3369 				break;
3370 			default:
3371 				break;
3372 		}
3373 	}
3374 }
3375 
itemAdd(PageItem::ItemType itemType,PageItem::ItemFrameType frameType,double x,double y,double b,double h,double w,const QString & fill,const QString & stroke)3376 PageItem* CgmPlug::itemAdd(PageItem::ItemType itemType, PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& stroke)
3377 {
3378 	int z;
3379 	if (lineVisible)
3380 	{
3381 		if (fillType == 0)
3382 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, CommonStrings::None, stroke);
3383 		else if ((fillType == 1) || (fillType == 3))
3384 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, fill, stroke);
3385 		else if (fillType == 2)
3386 		{
3387 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, fill, stroke);
3388 			if (patternTable.contains(patternIndex))
3389 			{
3390 				PageItem *ite = m_Doc->Items->at(z);
3391 				ite->setPattern(patternTable[patternIndex]);
3392 				ScPattern pat = m_Doc->docPatterns[patternTable[patternIndex]];
3393 				double patSX = 100;
3394 				double patSY = 100;
3395 				if (patternScaleX > -1)
3396 					patSX = patternScaleX / pat.width * 100;
3397 				if (patternScaleY > -1)
3398 					patSY = patternScaleY / pat.height * 100;
3399 				ite->setPatternTransform(patSX, patSY, 0, 0, 0, 0.0, 0.0);
3400 				ite->GrType = Gradient_Pattern;
3401 			}
3402 		}
3403 		else if (fillType == 4)
3404 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, CommonStrings::None, stroke);
3405 		else
3406 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, fill, stroke);
3407 	}
3408 	else
3409 	{
3410 		if (fillType == 0)
3411 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, CommonStrings::None, fill);
3412 		else if ((fillType == 1) || (fillType == 3))
3413 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, fill, CommonStrings::None);
3414 		else if (fillType == 2)
3415 		{
3416 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, fill, CommonStrings::None);
3417 			if (patternTable.contains(patternIndex))
3418 			{
3419 				PageItem *ite = m_Doc->Items->at(z);
3420 				ite->setPattern(patternTable[patternIndex]);
3421 				ScPattern pat = m_Doc->docPatterns[patternTable[patternIndex]];
3422 				double patSX = 100;
3423 				double patSY = 100;
3424 				if (patternScaleX > -1)
3425 					patSX = patternScaleX / pat.width * 100;
3426 				if (patternScaleY > -1)
3427 					patSY = patternScaleY / pat.height * 100;
3428 				ite->setPatternTransform(patSX, patSY, 0, 0, 0, 0.0, 0.0);
3429 				ite->GrType = Gradient_Pattern;
3430 			}
3431 		}
3432 		else
3433 			z = m_Doc->itemAdd(itemType, frameType, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
3434 	}
3435 	return m_Doc->Items->at(z);
3436 }
3437 
finishItem(PageItem * ite,bool line)3438 void CgmPlug::finishItem(PageItem* ite, bool line)
3439 {
3440 	ite->ClipEdited = true;
3441 	ite->FrameType = 3;
3442 	FPoint wh = getMaxClipF(&ite->PoLine);
3443 	ite->setWidthHeight(wh.x(),wh.y());
3444 	ite->setTextFlowMode(PageItem::TextFlowDisabled);
3445 	m_Doc->adjustItemSize(ite);
3446 	ite->OldB2 = ite->width();
3447 	ite->OldH2 = ite->height();
3448 	if (line)
3449 	{
3450 		ite->setLineStyle(lineType);
3451 		ite->setLineEnd(lineCap);
3452 		ite->setLineJoin(lineJoin);
3453 	}
3454 	else
3455 	{
3456 		ite->setLineStyle(edgeType);
3457 		ite->setLineEnd(edgeCap);
3458 		ite->setLineJoin(edgeJoin);
3459 	}
3460 	ite->updateClip();
3461 	Elements.append(ite);
3462 	if (groupStack.count() != 0)
3463 		groupStack.top().append(ite);
3464 	Coords.resize(0);
3465 	Coords.svgInit();
3466 }
3467