1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 
8 #include <QByteArray>
9 #include <QCursor>
10 #include <QDrag>
11 #include <QFile>
12 #include <QList>
13 #include <QMimeData>
14 #include <QRegExp>
15 #include <QTextCodec>
16 #include <QStack>
17 #include <QDebug>
18 
19 #include <cstdlib>
20 
21 #include "importpct.h"
22 
23 #include "commonstrings.h"
24 #include "loadsaveplugin.h"
25 #include "pageitem_imageframe.h"
26 #include "pagesize.h"
27 #include "prefscontext.h"
28 #include "prefsfile.h"
29 #include "prefsmanager.h"
30 #include "prefstable.h"
31 #include "rawimage.h"
32 #include "scclocale.h"
33 #include "sccolorengine.h"
34 #include "scconfig.h"
35 #include "scmimedata.h"
36 #include "scpaths.h"
37 #include "scpattern.h"
38 #include "scribusXml.h"
39 #include "scribuscore.h"
40 #include "scribusdoc.h"
41 #include "scribusview.h"
42 #include "sctextstream.h"
43 #include "selection.h"
44 #include "ui/customfdialog.h"
45 #include "ui/missing.h"
46 #include "ui/multiprogressdialog.h"
47 #include "ui/propertiespalette.h"
48 #include "undomanager.h"
49 #include "util.h"
50 #include "util_formats.h"
51 #include "util_math.h"
52 
PctPlug(ScribusDoc * doc,int flags)53 PctPlug::PctPlug(ScribusDoc* doc, int flags)
54 {
55 	tmpSel=new Selection(this, false);
56 	m_Doc=doc;
57 	importerFlags = flags;
58 	interactive = (flags & LoadSavePlugin::lfInteractive);
59 	progressDialog = nullptr;
60 }
61 
readThumbnail(const QString & fName)62 QImage PctPlug::readThumbnail(const QString& fName)
63 {
64 	QFileInfo fi = QFileInfo(fName);
65 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
66 	double b {0.0};
67 	double h {0.0};
68 	double x {0.0};
69 	double y {0.0};
70 	parseHeader(fName, x, y, b, h);
71 	if (b == 0.0)
72 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
73 	if (h == 0.0)
74 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
75 	docWidth = b;
76 	docHeight = h;
77 	progressDialog = nullptr;
78 	m_Doc = new ScribusDoc();
79 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
80 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
81 	m_Doc->addPage(0);
82 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
83 	baseX = m_Doc->currentPage()->xOffset() - x;
84 	baseY = m_Doc->currentPage()->yOffset() - y;
85 	Elements.clear();
86 	m_Doc->setLoading(true);
87 	m_Doc->DoDrawing = false;
88 	m_Doc->scMW()->setScriptRunning(true);
89 	QString CurDirP = QDir::currentPath();
90 	QDir::setCurrent(fi.path());
91 	if (convert(fName))
92 	{
93 		tmpSel->clear();
94 		QDir::setCurrent(CurDirP);
95 		if (Elements.count() > 1)
96 			m_Doc->groupObjectsList(Elements);
97 		m_Doc->DoDrawing = true;
98 		m_Doc->m_Selection->delaySignalsOn();
99 		QImage tmpImage;
100 		if (Elements.count() > 0)
101 		{
102 			for (int dre=0; dre<Elements.count(); ++dre)
103 			{
104 				tmpSel->addItem(Elements.at(dre), true);
105 			}
106 			tmpSel->setGroupRect();
107 			double xs = tmpSel->width();
108 			double ys = tmpSel->height();
109 			tmpImage = Elements.at(0)->DrawObj_toImage(500);
110 			tmpImage.setText("XSize", QString("%1").arg(xs));
111 			tmpImage.setText("YSize", QString("%1").arg(ys));
112 		}
113 		m_Doc->scMW()->setScriptRunning(false);
114 		m_Doc->setLoading(false);
115 		m_Doc->m_Selection->delaySignalsOff();
116 		delete m_Doc;
117 		return tmpImage;
118 	}
119 	QDir::setCurrent(CurDirP);
120 	m_Doc->DoDrawing = true;
121 	m_Doc->scMW()->setScriptRunning(false);
122 	delete m_Doc;
123 	return QImage();
124 }
125 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)126 bool PctPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
127 {
128 	bool success = false;
129 	interactive = (flags & LoadSavePlugin::lfInteractive);
130 	importerFlags = flags;
131 	cancel = false;
132 	bool ret = false;
133 	CustColors.clear();
134 	QFileInfo fi = QFileInfo(fNameIn);
135 	if ( !ScCore->usingGUI() )
136 	{
137 		interactive = false;
138 		showProgress = false;
139 	}
140 	baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
141 	if ( showProgress )
142 	{
143 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
144 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
145 		QStringList barNames, barTexts;
146 		barNames << "GI";
147 		barTexts << tr("Analyzing File:");
148 		QList<bool> barsNumeric;
149 		barsNumeric << false;
150 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
151 		progressDialog->setOverallTotalSteps(3);
152 		progressDialog->setOverallProgress(0);
153 		progressDialog->setProgress("GI", 0);
154 		progressDialog->show();
155 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
156 		qApp->processEvents();
157 	}
158 	else
159 		progressDialog = nullptr;
160 /* Set default Page to size defined in Preferences */
161 	double x = 0.0;
162 	double y = 0.0;
163 	double b = 0.0;
164 	double h = 0.0;
165 	if (progressDialog)
166 	{
167 		progressDialog->setOverallProgress(1);
168 		qApp->processEvents();
169 	}
170 	parseHeader(fNameIn, x, y, b, h);
171 	if (b == 0.0)
172 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
173 	if (h == 0.0)
174 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
175 	docWidth = b;
176 	docHeight = h;
177 	baseX = 0;
178 	baseY = 0;
179 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
180 	{
181 		m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
182 		m_Doc->addPage(0);
183 		m_Doc->view()->addPage(0, true);
184 		m_Doc->currentPage()->setInitialWidth(docWidth);
185 		m_Doc->currentPage()->setInitialHeight(docHeight);
186 		m_Doc->currentPage()->setWidth(docWidth);
187 		m_Doc->currentPage()->setHeight(docHeight);
188 		m_Doc->currentPage()->setMasterPageNameNormal();
189 		m_Doc->currentPage()->setSize("Custom");
190 		m_Doc->reformPages(true);
191 		baseX = m_Doc->currentPage()->xOffset();
192 		baseY = m_Doc->currentPage()->yOffset();
193 	}
194 	else
195 	{
196 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
197 		{
198 			m_Doc = ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
199 			ScCore->primaryMainWindow()->HaveNewDoc();
200 			m_Doc->setPageHeight(docHeight);
201 			m_Doc->setPageWidth(docWidth);
202 			m_Doc->currentPage()->setInitialWidth(docWidth);
203 			m_Doc->currentPage()->setInitialHeight(docHeight);
204 			m_Doc->currentPage()->setWidth(docWidth);
205 			m_Doc->currentPage()->setHeight(docHeight);
206 			ret = true;
207 			baseX = m_Doc->currentPage()->xOffset();
208 			baseY = m_Doc->currentPage()->yOffset();
209 		}
210 	}
211 	offsetX += m_Doc->currentPage()->xOffset();
212 	offsetY += m_Doc->currentPage()->yOffset();
213 	offsetX *= -1;
214 	offsetY *= -1;
215 	if ((!ret) && (interactive))
216 	{
217 		baseX = m_Doc->currentPage()->xOffset();
218 		baseY = m_Doc->currentPage()->yOffset();
219 	}
220 	if ((ret) || (!interactive))
221 	{
222 		if (docWidth > docHeight)
223 			m_Doc->setPageOrientation(1);
224 		else
225 			m_Doc->setPageOrientation(0);
226 		m_Doc->setPageSize("Custom");
227 	}
228 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
229 		m_Doc->view()->deselectItems();
230 	Elements.clear();
231 	m_Doc->setLoading(true);
232 	m_Doc->DoDrawing = false;
233 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
234 		m_Doc->view()->updatesOn(false);
235 	m_Doc->scMW()->setScriptRunning(true);
236 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
237 	QString CurDirP = QDir::currentPath();
238 	QDir::setCurrent(fi.path());
239 	if (convert(fNameIn))
240 	{
241 		tmpSel->clear();
242 		QDir::setCurrent(CurDirP);
243 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
244 			m_Doc->groupObjectsList(Elements);
245 		m_Doc->DoDrawing = true;
246 		m_Doc->scMW()->setScriptRunning(false);
247 		m_Doc->setLoading(false);
248 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
249 		if ((Elements.count() > 0) && (!ret) && (interactive))
250 		{
251 			if (flags & LoadSavePlugin::lfScripted)
252 			{
253 				bool loadF = m_Doc->isLoading();
254 				m_Doc->setLoading(false);
255 				m_Doc->changed();
256 				m_Doc->setLoading(loadF);
257 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
258 				{
259 					m_Doc->m_Selection->delaySignalsOn();
260 					for (int dre=0; dre<Elements.count(); ++dre)
261 					{
262 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
263 					}
264 					m_Doc->m_Selection->delaySignalsOff();
265 					m_Doc->m_Selection->setGroupRect();
266 					if (m_Doc->view() != nullptr)
267 						m_Doc->view()->updatesOn(true);
268 				}
269 			}
270 			else
271 			{
272 				m_Doc->DragP = true;
273 				m_Doc->DraggedElem = nullptr;
274 				m_Doc->DragElements.clear();
275 				m_Doc->m_Selection->delaySignalsOn();
276 				for (int dre=0; dre<Elements.count(); ++dre)
277 				{
278 					tmpSel->addItem(Elements.at(dre), true);
279 				}
280 				tmpSel->setGroupRect();
281 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
282 				m_Doc->itemSelection_DeleteItem(tmpSel);
283 				m_Doc->view()->updatesOn(true);
284 				if (importedColors.count() != 0)
285 				{
286 					for (int cd = 0; cd < importedColors.count(); cd++)
287 					{
288 						m_Doc->PageColors.remove(importedColors[cd]);
289 					}
290 				}
291 				if (importedPatterns.count() != 0)
292 				{
293 					for (int cd = 0; cd < importedPatterns.count(); cd++)
294 					{
295 						m_Doc->docPatterns.remove(importedPatterns[cd]);
296 					}
297 				}
298 				m_Doc->m_Selection->delaySignalsOff();
299 				// We must copy the TransationSettings object as it is owned
300 				// by handleObjectImport method afterwards
301 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
302 				m_Doc->view()->handleObjectImport(md, transacSettings);
303 				m_Doc->DragP = false;
304 				m_Doc->DraggedElem = nullptr;
305 				m_Doc->DragElements.clear();
306 			}
307 		}
308 		else
309 		{
310 			m_Doc->changed();
311 			m_Doc->reformPages();
312 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
313 				m_Doc->view()->updatesOn(true);
314 		}
315 		success = true;
316 	}
317 	else
318 	{
319 		QDir::setCurrent(CurDirP);
320 		m_Doc->DoDrawing = true;
321 		m_Doc->scMW()->setScriptRunning(false);
322 		m_Doc->view()->updatesOn(true);
323 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
324 	}
325 	if (interactive)
326 		m_Doc->setLoading(false);
327 	//CB If we have a gui we must refresh it if we have used the progressbar
328 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
329 	{
330 		if ((showProgress) && (!interactive))
331 			m_Doc->view()->DrawNew();
332 	}
333 	qApp->restoreOverrideCursor();
334 	return success;
335 }
336 
~PctPlug()337 PctPlug::~PctPlug()
338 {
339 	delete progressDialog;
340 	delete tmpSel;
341 }
342 
parseHeader(const QString & fName,double & x,double & y,double & b,double & h)343 void PctPlug::parseHeader(const QString& fName, double &x, double &y, double &b, double &h)
344 {
345 	QFile f(fName);
346 	if (f.open(QIODevice::ReadOnly))
347 	{
348 		QDataStream ts(&f);
349 		ts.setByteOrder(QDataStream::BigEndian);
350 		ts.device()->seek(512);
351 		qint16 pgX, pgY, pgW, pgH, dummy;
352 		ts >> dummy >> pgX >> pgY >> pgW >> pgH;
353 		quint16 vers, vers2, vers3;
354 		ts >> vers;
355 		if (vers == 0x1101)
356 		{
357 			pctVersion = 1;
358 			h = pgW - pgX;
359 			b = pgH - pgY;
360 			x = pgY;
361 			y = pgX;
362 			offsetX = x;
363 			offsetY = y;
364 			resX = 1.0;
365 			resY = 1.0;
366 		}
367 		else if (vers == 0x0011)
368 		{
369 			ts >> vers2 >> vers3;
370 			if ((vers2 == 0x02FF) && (vers3 == 0x0C00))
371 			{
372 				pctVersion = 2;
373 				qint16 vExt;
374 				ts >> vExt;
375 				if (vExt == -1)
376 				{
377 					ts >> dummy;
378 				//	quint32 xres, yres;
379 				//	xres = 72;
380 				//	yres = 72;
381 					resX = 1.0;
382 					resY = 1.0;
383 					qint32 pgX2, pgY2, pgW2, pgH2;
384 					ts >> pgX2 >> pgY2 >> pgW2 >> pgH2;
385 					ts >> dummy;
386 					ts >> dummy;
387 					h = pgW - pgX;
388 					b = pgH - pgY;
389 					x = pgY;
390 					y = pgX;
391 					offsetX = x;
392 					offsetY = y;
393 				}
394 				else if (vExt == -2)
395 				{
396 					ts >> dummy;
397 					quint16 xres, yres;
398 					ts >> xres >> dummy >> yres >> dummy;
399 					ts >> pgX >> pgY >> pgW >> pgH;
400 					ts >> dummy;
401 					resX = 72.0 / static_cast<double>(xres);
402 					resY = 72.0 / static_cast<double>(yres);
403 					h = (pgW - pgX) * resX;
404 					b = (pgH - pgY) * resY;
405 					x = pgY * resX;
406 					y = pgX * resY;
407 					offsetX = x;
408 					offsetY = y;
409 				}
410 			}
411 		}
412 		f.close();
413 //		qDebug() << "W" << b << "H" << h;
414 	}
415 }
416 
convert(const QString & fn)417 bool PctPlug::convert(const QString& fn)
418 {
419 	CurrColorFill = "White";
420 	CurrFillShade = 100.0;
421 	CurrColorStroke = "Black";
422 	CurrStrokeShade = 100.0;
423 	patternMode = false;
424 	patternData.resize(0);
425 	backColor = Qt::white;
426 	foreColor = Qt::black;
427 	Coords.resize(0);
428 	Coords.svgInit();
429 	LineW = 1.0;
430 	currentPoint = QPoint(0, 0);
431 	currentPointT = QPoint(0, 0);
432 	ovalSize = QPoint(0, 0);
433 	fontMap.clear();
434 	currentTextSize = 12;
435 	currentFontID = 0;
436 	currentFontStyle = 0;
437 	imageData.resize(0);
438 	lineMode = false;
439 	skipOpcode = false;
440 	postscriptMode = false;
441 	textIsPostScript = false;
442 	importedColors.clear();
443 	importedPatterns.clear();
444 	QList<PageItem*> gElements;
445 	groupStack.push(gElements);
446 	currentItemNr = 0;
447 	if (progressDialog)
448 	{
449 		progressDialog->setOverallProgress(2);
450 		progressDialog->setLabel("GI", tr("Generating Items"));
451 		qApp->processEvents();
452 	}
453 	QFile f(fn);
454 	if (f.open(QIODevice::ReadOnly))
455 	{
456 		int fSize = (int) f.size();
457 		if (progressDialog)
458 		{
459 			progressDialog->setTotalSteps("GI", fSize);
460 			qApp->processEvents();
461 		}
462 		QDataStream ts(&f);
463 		ts.setByteOrder(QDataStream::BigEndian);
464 		ts.device()->seek(522);
465 		quint16 vers = 0;
466 		ts >> vers;
467 		while (vers == 0)
468 		{
469 			ts >> vers;
470 			if (vers == 0x00FF)
471 			{
472 				if (progressDialog)
473 					progressDialog->close();
474 				f.close();
475 				return false;
476 			}
477 		}
478 		if (vers == 0x1101)
479 		{
480 			pctVersion = 1;		// Pict Version 1
481 			parsePict(ts);
482 		}
483 		else
484 		{
485 			ts.skipRawData(4);	// skip the next 4 Bytes
486 			ts >> vers;		// read the version info
487 //			if (vers == 0x0FFFE)
488 				pctVersion = 2;	// Pict Extended Version 2
489 //			else if (vers == 0x0FFFF)
490 //				pctVersion = 3;	// Pict Version 2
491 //			else
492 //			{
493 //				if (progressDialog)
494 //					progressDialog->close();
495 //				f.close();
496 //				return false;	// bail out, no Mac Pict
497 //			}
498 			ts.skipRawData(22);
499 			parsePict(ts);
500 		}
501 		if (Elements.count() == 0)
502 		{
503 			if (importedColors.count() != 0)
504 			{
505 				for (int cd = 0; cd < importedColors.count(); cd++)
506 				{
507 					m_Doc->PageColors.remove(importedColors[cd]);
508 				}
509 			}
510 			if (importedPatterns.count() != 0)
511 			{
512 				for (int cd = 0; cd < importedPatterns.count(); cd++)
513 				{
514 					m_Doc->docPatterns.remove(importedPatterns[cd]);
515 				}
516 			}
517 		}
518 		f.close();
519 	}
520 	if (progressDialog)
521 		progressDialog->close();
522 	return true;
523 }
524 
parsePict(QDataStream & ts)525 void PctPlug::parsePict(QDataStream &ts)
526 {
527 	while (!ts.atEnd())
528 	{
529 		quint16 opCode, dataLen;
530 		quint8 dataLenByte;
531 		quint32 dataLenLong;
532 		if (pctVersion == 1)
533 		{
534 			ts >> dataLenByte;
535 			opCode = dataLenByte;
536 		}
537 		else
538 			ts >> opCode;
539 		if (((opCode >= 0x0092) && (opCode <= 0x0097)) || ((opCode >= 0x009C) && (opCode <= 0x009F)) || ((opCode >= 0x00A2) && (opCode <= 0x00AF)))
540 		{
541 			// Reserved by Apple
542 //			qDebug() << "Reserved by Apple";
543 			ts >> dataLen;
544 			alignStreamToWord(ts, dataLen);
545 		}
546 		else if (((opCode >= 0x00B0) && (opCode <= 0x00CF)) || ((opCode >= 0x8000) && (opCode <= 0x80FF)))
547 		{
548 			// Reserved by Apple
549 //			qDebug() << "Reserved by Apple";
550 		}
551 		else if (((opCode >= 0x00D0) && (opCode <= 0x00FE)) || ((opCode >= 0x8100) && (opCode <= 0x81FF)))
552 		{
553 			// Reserved by Apple
554 //			qDebug() << "Reserved by Apple";
555 			ts >> dataLenLong;
556 			alignStreamToWord(ts, dataLenLong);
557 		}
558 		else if (((opCode >= 0x0100) && (opCode <= 0x01FF)) || ((opCode >= 0x02FF) && (opCode <= 0x0BFE)))
559 		{
560 			// Reserved by Apple
561 //			qDebug() << "Reserved by Apple";
562 			alignStreamToWord(ts, 2);
563 		}
564 		else if ((opCode >= 0x0C00) && (opCode <= 0x7EFF))
565 		{
566 			// Reserved by Apple
567 //			qDebug() << "Reserved by Apple";
568 			alignStreamToWord(ts, 24);
569 		}
570 		else if ((opCode >= 0x7F00) && (opCode <= 0x7FFF))
571 		{
572 			// Reserved by Apple
573 //			qDebug() << "Reserved by Apple";
574 			alignStreamToWord(ts, 254);
575 		}
576 		else
577 		{
578 			switch (opCode)
579 			{
580 				case 0x0000:		// NOP
581 //					qDebug() << "NOP";
582 					break;
583 				case 0x0001:		// Clipping Region
584 //					qDebug() << "Clipping Region";
585 					ts >> dataLen;
586 					alignStreamToWord(ts, dataLen-2);
587 					break;
588 				case 0x0002:		// Background Pattern
589 					handleLineModeEnd();
590 //					qDebug() << "Background Pattern";
591 					alignStreamToWord(ts, 8);
592 					break;
593 				case 0x0003:		// Text Font
594 					handleTextFont(ts);
595 					break;
596 				case 0x0004:		// Text Style
597 					handleTextStyle(ts);
598 					break;
599 				case 0x0005:		// Text Mode
600 					handleLineModeEnd();
601 					ts >> dataLen;
602 //					qDebug() << "Text Mode" << dataLen;
603 //					alignStreamToWord(ts, 2);
604 					break;
605 				case 0x0006:		// Extra Space
606 //					qDebug() << "Extra Space";
607 					alignStreamToWord(ts, 4);
608 					break;
609 				case 0x0007:		// Pen Size
610 					handlePenSize(ts);
611 					break;
612 				case 0x0008:		// Pen Mode
613 					handleLineModeEnd();
614 					ts >> dataLen;
615 //					qDebug() << "Pen Mode" << dataLen;
616 //					alignStreamToWord(ts, 2);
617 					break;
618 				case 0x0009:		// Pen Pattern
619 					handlePenPattern(ts);
620 					break;
621 				case 0x000A:		// Fill Pattern
622 					handleLineModeEnd();
623 //					qDebug() << "Fill Pattern";
624 					alignStreamToWord(ts, 8);
625 					break;
626 				case 0x000B:		// Oval Size
627 					handleOvalSize(ts);
628 					break;
629 				case 0x000C:		// Origin
630 //					qDebug() << "Origin";
631 					alignStreamToWord(ts, 4);
632 					break;
633 				case 0x000D:		// Text Size
634 					handleTextSize(ts);
635 					break;
636 				case 0x000E:		// Foreground Color
637 					handleColor(ts, false);
638 					break;
639 				case 0x000F:		// Background Color
640 					handleColor(ts, true);
641 					break;
642 				case 0x0010:		// Text Ratio
643 					handleLineModeEnd();
644 //					qDebug() << "Text Ratio";
645 					alignStreamToWord(ts, 8);
646 					break;
647 				case 0x0011:		// Version
648 //					qDebug() << "Version";
649 					alignStreamToWord(ts, 1);
650 					break;
651 				case 0x0015:		// Fractional pen position
652 					handleLineModeEnd();
653 //					qDebug() << "Fractional pen position at" << ts.device()->pos();
654 					alignStreamToWord(ts, 2);
655 					break;
656 				case 0x0016:		// Extra char space
657 //					qDebug() << "Extra char space";
658 					alignStreamToWord(ts, 2);
659 					break;
660 				case 0x0017:
661 				case 0x0018:
662 				case 0x0019:
663 //					qDebug() << "Reserved by Apple";
664 					break;
665 				case 0x001A:		// Foreground color RGB
666 					handleColorRGB(ts, false);
667 					break;
668 				case 0x001B:		// Background color RGB
669 					handleColorRGB(ts, true);
670 					break;
671 				case 0x001C:		// Highlight mode
672 //					qDebug() << "Highlight mode";
673 					break;
674 				case 0x001D:		// Highlight color RGB
675 //					qDebug() << "Highlight color RGB";
676 					alignStreamToWord(ts, 6);
677 					break;
678 				case 0x001E:		// Use default highlight color
679 //					qDebug() << "Use default highlight color";
680 					break;
681 				case 0x0020:		// Line
682 					handleLine(ts);
683 					break;
684 				case 0x0021:		// Line To
685 					handleLineFrom(ts);
686 					break;
687 				case 0x0022:		// Short Line
688 					handleShortLine(ts);
689 					break;
690 				case 0x0023:		// Short Line To
691 					handleShortLineFrom(ts);
692 					break;
693 				case 0x0024:
694 				case 0x0025:
695 				case 0x0026:
696 				case 0x0027:		// Reserved by Apple
697 //					qDebug() << "Reserved by Apple";
698 					ts >> dataLen;
699 					alignStreamToWord(ts, dataLen);
700 					break;
701 				case 0x0028:		// Long Text
702 					handleLongText(ts);
703 					break;
704 				case 0x0029:		// Text DH
705 					handleDHText(ts);
706 					break;
707 				case 0x002A:		// Text DV
708 					handleDVText(ts);
709 					break;
710 				case 0x002B:		// Text DHV
711 					handleDHVText(ts);
712 					break;
713 				case 0x002C:		// Font Name
714 					handleFontName(ts);
715 					break;
716 				case 0x002D:		// Line justify
717 					handleLineModeEnd();
718 //					qDebug() << "Line justify";
719 					alignStreamToWord(ts, 10);
720 					break;
721 				case 0x002E:		// Glyph state
722 					handleLineModeEnd();
723 //					qDebug() << "Glyph state";
724 					ts >> dataLen;
725 					alignStreamToWord(ts, dataLen);
726 					break;
727 				case 0x002F:		// Reserved by Apple
728 //					qDebug() << "Reserved by Apple";
729 					ts >> dataLen;
730 					alignStreamToWord(ts, dataLen);
731 					break;
732 				case 0x0030:		// Frame rect
733 				case 0x0031:		// Paint rect
734 				case 0x0032:		// Erase rect
735 				case 0x0033:		// Invert rect
736 				case 0x0034:		// Fill rect
737 					handleShape(ts, opCode);
738 					break;
739 				case 0x0035:
740 				case 0x0036:
741 				case 0x0037:		// Reserved by Apple
742 //					qDebug() << "Reserved by Apple";
743 					alignStreamToWord(ts, 8);
744 					break;
745 				case 0x0038:		// Frame same rect
746 				case 0x0039:		// Paint same rect
747 				case 0x003A:		// Erase same rect
748 				case 0x003B:		// Invert same rect
749 				case 0x003C:		// Fill same rect
750 					handleSameShape(ts, opCode);
751 					break;
752 				case 0x003D:
753 				case 0x003E:
754 				case 0x003F:		// Reserved by Apple
755 //					qDebug() << "Reserved by Apple";
756 					break;
757 				case 0x0040:		// Frame round rect
758 				case 0x0041:		// Paint round rect
759 				case 0x0042:		// Erase round rect
760 				case 0x0043:		// Invert round rect
761 				case 0x0044:		// Fill round rect
762 					handleShape(ts, opCode);
763 					break;
764 				case 0x0045:
765 				case 0x0046:
766 				case 0x0047:		// Reserved by Apple
767 //					qDebug() << "Reserved by Apple";
768 					alignStreamToWord(ts, 8);
769 					break;
770 				case 0x0048:		// Frame same round rect
771 				case 0x0049:		// Paint same round rect
772 				case 0x004A:		// Erase same round rect
773 				case 0x004B:		// Invert same round rect
774 				case 0x004C:		// Fill same round rect
775 					handleSameShape(ts, opCode);
776 					break;
777 				case 0x004D:
778 				case 0x004E:
779 				case 0x004F:		// Reserved by Apple
780 //					qDebug() << "Reserved by Apple";
781 					break;
782 				case 0x0050:		// Frame oval
783 				case 0x0051:		// Paint oval
784 				case 0x0052:		// Erase oval
785 				case 0x0053:		// Invert oval
786 				case 0x0054:		// Fill oval
787 					handleShape(ts, opCode);
788 					break;
789 				case 0x0055:
790 				case 0x0056:
791 				case 0x0057:		// Reserved by Apple
792 //					qDebug() << "Reserved by Apple";
793 					alignStreamToWord(ts, 8);
794 					break;
795 				case 0x0058:		// Frame same oval
796 				case 0x0059:		// Paint same oval
797 				case 0x005A:		// Erase same oval
798 				case 0x005B:		// Invert same oval
799 				case 0x005C:		// Fill same oval
800 					handleSameShape(ts, opCode);
801 					break;
802 				case 0x005D:
803 				case 0x005E:
804 				case 0x005F:		// Reserved by Apple
805 //					qDebug() << "Reserved by Apple";
806 					break;
807 				case 0x0060:		// Frame arc
808 					handleLineModeEnd();
809 //					qDebug() << "Frame arc";
810 					alignStreamToWord(ts, 12);
811 					break;
812 				case 0x0061:		// Paint arc
813 					handleLineModeEnd();
814 //					qDebug() << "Paint arc";
815 					alignStreamToWord(ts, 12);
816 					break;
817 				case 0x0062:		// Erase arc
818 					handleLineModeEnd();
819 //					qDebug() << "Erase arc";
820 					alignStreamToWord(ts, 12);
821 					break;
822 				case 0x0063:		// Invert arc
823 					handleLineModeEnd();
824 //					qDebug() << "Invert arc";
825 					alignStreamToWord(ts, 12);
826 					break;
827 				case 0x0064:		// Fill arc
828 					handleLineModeEnd();
829 //					qDebug() << "Fill arc";
830 					alignStreamToWord(ts, 12);
831 					break;
832 				case 0x0065:
833 				case 0x0066:
834 				case 0x0067:		// Reserved by Apple
835 //					qDebug() << "Reserved by Apple";
836 					alignStreamToWord(ts, 12);
837 					break;
838 				case 0x0068:		// Frame same arc
839 					handleLineModeEnd();
840 //					qDebug() << "Frame same arc";
841 					alignStreamToWord(ts, 4);
842 					break;
843 				case 0x0069:		// Paint same arc
844 					handleLineModeEnd();
845 //					qDebug() << "Paint same arc";
846 					alignStreamToWord(ts, 4);
847 					break;
848 				case 0x006A:		// Erase same arc
849 					handleLineModeEnd();
850 //					qDebug() << "Erase same arc";
851 					alignStreamToWord(ts, 4);
852 					break;
853 				case 0x006B:		// Invert same arc
854 					handleLineModeEnd();
855 //					qDebug() << "Invert same arc";
856 					alignStreamToWord(ts, 4);
857 					break;
858 				case 0x006C:		// Fill same arc
859 					handleLineModeEnd();
860 //					qDebug() << "Fill same arc";
861 					alignStreamToWord(ts, 4);
862 					break;
863 				case 0x006D:
864 				case 0x006E:
865 				case 0x006F:		// Reserved by Apple
866 //					qDebug() << "Reserved by Apple";
867 					alignStreamToWord(ts, 4);
868 					break;
869 				case 0x0070:		// Frame poly
870 				case 0x0071:		// Paint poly
871 				case 0x0072:		// Erase poly
872 				case 0x0073:		// Invert poly
873 				case 0x0074:		// Fill poly
874 					handlePolygon(ts, opCode);
875 					break;
876 				case 0x0075:
877 				case 0x0076:
878 				case 0x0077:		// Reserved by Apple
879 //					qDebug() << "Reserved by Apple";
880 					ts >> dataLen;
881 					alignStreamToWord(ts, dataLen-2);
882 					break;
883 				case 0x0078:		// Frame same poly
884 					handleLineModeEnd();
885 //					qDebug() << "Frame same poly";
886 					break;
887 				case 0x0079:		// Paint same poly
888 					handleLineModeEnd();
889 //					qDebug() << "Paint same poly";
890 					break;
891 				case 0x007A:		// Erase same poly
892 					handleLineModeEnd();
893 //					qDebug() << "Erase same poly";
894 					break;
895 				case 0x007B:		// Invert same poly
896 					handleLineModeEnd();
897 //					qDebug() << "Invert same poly";
898 					break;
899 				case 0x007C:		// Fill same poly
900 					handleLineModeEnd();
901 //					qDebug() << "Fill same poly";
902 					break;
903 				case 0x007D:
904 				case 0x007E:
905 				case 0x007F:		// Reserved by Apple
906 //					qDebug() << "Reserved by Apple";
907 					break;
908 				case 0x0080:		// Frame region
909 //					qDebug() << "Frame region";
910 					ts >> dataLen;
911 					alignStreamToWord(ts, dataLen-2);
912 					break;
913 				case 0x0081:		// Paint region
914 					handleLineModeEnd();
915 //					qDebug() << "Paint region";
916 					ts >> dataLen;
917 					alignStreamToWord(ts, dataLen-2);
918 					break;
919 				case 0x0082:		// Erase region
920 					handleLineModeEnd();
921 //					qDebug() << "Erase region";
922 					ts >> dataLen;
923 					alignStreamToWord(ts, dataLen-2);
924 					break;
925 				case 0x0083:		// Invert region
926 					handleLineModeEnd();
927 //					qDebug() << "Invert region";
928 					ts >> dataLen;
929 					alignStreamToWord(ts, dataLen-2);
930 					break;
931 				case 0x0084:		// Fill region
932 					handleLineModeEnd();
933 //					qDebug() << "Fill region";
934 					ts >> dataLen;
935 					alignStreamToWord(ts, dataLen-2);
936 					break;
937 				case 0x0085:
938 				case 0x0086:
939 				case 0x0087:		// Reserved by Apple
940 //					qDebug() << "Reserved by Apple";
941 					ts >> dataLen;
942 					alignStreamToWord(ts, dataLen-2);
943 					break;
944 				case 0x0088:		// Frame same region
945 					handleLineModeEnd();
946 //					qDebug() << "Frame same region";
947 					break;
948 				case 0x0089:		// Paint same region
949 					handleLineModeEnd();
950 //					qDebug() << "Paint same region";
951 					break;
952 				case 0x008A:		// Erase same region
953 					handleLineModeEnd();
954 //					qDebug() << "Erase same region";
955 					break;
956 				case 0x008B:		// Invert same region
957 					handleLineModeEnd();
958 //					qDebug() << "Invert same region";
959 					break;
960 				case 0x008C:		// Fill same region
961 					handleLineModeEnd();
962 //					qDebug() << "Fill same region";
963 					break;
964 				case 0x008D:
965 				case 0x008E:
966 				case 0x008F:		// Reserved by Apple
967 //					qDebug() << "Reserved by Apple";
968 					break;
969 				case 0x0090:		// Bits Rect
970 //					qDebug() << "Bits Rect";
971 					handlePixmap(ts, opCode);
972 					break;
973 				case 0x0091:		// Bits Region
974 //					qDebug() << "Bits Region";
975 					handlePixmap(ts, opCode);
976 					break;
977 				case 0x0098:		// Pack Bits Rect
978 //					qDebug() << "Pack Bits Rect";
979 					handlePixmap(ts, opCode);
980 					break;
981 				case 0x0099:		// Pack Bits Region
982 //					qDebug() << "Pack Bits Region";
983 					handlePixmap(ts, opCode);
984 					break;
985 				case 0x009A:		// Direct Bits Rect
986 //					qDebug() << "Direct Bits Rect";
987 					handlePixmap(ts, opCode);
988 					break;
989 				case 0x009B:		// Direct Bits Region
990 //					qDebug() << "Direct Bits Region";
991 					handlePixmap(ts, opCode);
992 					break;
993 				case 0x00A0:		// Short Comment
994 					handleComment(ts, false);
995 					break;
996 				case 0x00A1:		// Long Comment
997 					handleComment(ts, true);
998 					break;
999 				case 0x00FF:		// End of Pict
1000 					handleLineModeEnd();
1001 					if (imageData.size() > 0)
1002 					{
1003 						QImage image;
1004 						image.loadFromData(imageData);
1005 						image = image.convertToFormat(QImage::Format_ARGB32);
1006 						int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX, baseY, image.width() * resX, image.height() * resY, 0, m_Doc->itemToolPrefs().imageFillColor, CommonStrings::None);
1007 						PageItem *ite = m_Doc->Items->at(z);
1008 						QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pct_XXXXXX.png");
1009 						tempFile->setAutoRemove(false);
1010 						tempFile->open();
1011 						QString fileName = getLongPathName(tempFile->fileName());
1012 						tempFile->close();
1013 						ite->isInlineImage = true;
1014 						ite->isTempFile = true;
1015 						image.save(fileName, "PNG");
1016 						ite->moveBy(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1017 						ite->moveBy(offsetX, offsetY);
1018 						finishItem(ite);
1019 						m_Doc->loadPict(fileName, ite);
1020 						ite->setImageScalingMode(false, false);
1021 						delete tempFile;
1022 					}
1023 //					qDebug() << "End of Pict";
1024 					return;
1025 					break;
1026 				case 0x0200:		// Reserved by Apple
1027 //					qDebug() << "Reserved by Apple";
1028 					alignStreamToWord(ts, 4);
1029 					break;
1030 				case 0x8200:		// Compressed QuickTime
1031 				case 0x8201:		// Uncompressed QuickTime
1032 					handleQuickTime(ts, opCode);
1033 					break;
1034 				case 0xFFFF:		// Reserved by Apple
1035 //					qDebug() << "Reserved by Apple";
1036 					ts >> dataLenLong;
1037 					alignStreamToWord(ts, dataLenLong);
1038 					break;
1039 				default:
1040 //					qDebug() << QString("Not implemented OpCode: 0x%1 at %2").arg(opCode, 4, 16, QLatin1Char('0')).arg(ts.device()->pos()-2);
1041 					return;
1042 					break;
1043 			}
1044 		}
1045 		if (progressDialog)
1046 		{
1047 			progressDialog->setProgress("GI", ts.device()->pos());
1048 			qApp->processEvents();
1049 		}
1050 	}
1051 }
1052 
alignStreamToWord(QDataStream & ts,uint len)1053 void PctPlug::alignStreamToWord(QDataStream &ts, uint len)
1054 {
1055 	ts.skipRawData(len);
1056 	if (pctVersion == 1)
1057 		return;
1058 	uint adj = ts.device()->pos() % 2;
1059 	if (adj != 0)
1060 		ts.skipRawData(1);
1061 }
1062 
handleColor(QDataStream & ts,bool back)1063 void PctPlug::handleColor(QDataStream &ts, bool back)
1064 {
1065 
1066 	handleLineModeEnd();
1067 	QString tmpName = CommonStrings::None;
1068 	ScColor tmp;
1069 	quint16 Rc, Gc, Bc;
1070 	quint32 colVal;
1071 	ts >> colVal;
1072 //	qDebug() << "Color" << colVal << back;
1073 	switch (colVal)
1074 	{
1075 		case 30:
1076 			Rc = 0xFFFF;
1077 			Gc = 0xFFFF;
1078 			Bc = 0xFFFF;
1079 			break;
1080 		case 33:
1081 			Rc = 0x0000;
1082 			Gc = 0x0000;
1083 			Bc = 0x0000;
1084 			break;
1085 		case 69:
1086 			Rc = 0xFC00;
1087 			Gc = 0xF37D;
1088 			Bc = 0x052F;
1089 			break;
1090 		case 137:
1091 			Rc = 0xF2D7;
1092 			Gc = 0x0856;
1093 			Bc = 0x84EC;
1094 			break;
1095 		case 205:
1096 			Rc = 0xDD6B;
1097 			Gc = 0x08C2;
1098 			Bc = 0x06A2;
1099 			break;
1100 		case 273:
1101 			Rc = 0x0241;
1102 			Gc = 0xAB54;
1103 			Bc = 0xEAFF;
1104 			break;
1105 		case 341:
1106 			Rc = 0x0000;
1107 			Gc = 0x64AF;
1108 			Bc = 0x11B0;
1109 			break;
1110 		case 409:
1111 			Rc = 0x0000;
1112 			Gc = 0x0000;
1113 			Bc = 0xD400;
1114 			break;
1115 		default:
1116 			Rc = 0x0000;
1117 			Gc = 0x0000;
1118 			Bc = 0x0000;
1119 			break;
1120 	}
1121 	int redC, greenC, blueC;
1122 	redC = qRound((Rc / 65535.0) * 255.0);
1123 	greenC = qRound((Gc / 65535.0) * 255.0);
1124 	blueC = qRound((Bc / 65535.0) * 255.0);
1125 	QColor c = QColor(redC, greenC, blueC);
1126 	tmp.setRgbColor(redC, greenC, blueC);
1127 	tmp.setSpotColor(false);
1128 	tmp.setRegistrationColor(false);
1129 	tmpName = "FromPict"+c.name();
1130 	QString fNam = m_Doc->PageColors.tryAddColor(tmpName, tmp);
1131 	if (fNam == tmpName)
1132 		importedColors.append(tmpName);
1133 	tmpName = fNam;
1134 	if (back)
1135 	{
1136 		CurrColorFill = tmpName;
1137 		backColor = c;
1138 	}
1139 	else
1140 	{
1141 		CurrColorStroke = tmpName;
1142 		foreColor = c;
1143 	}
1144 }
1145 
handleColorRGB(QDataStream & ts,bool back)1146 void PctPlug::handleColorRGB(QDataStream &ts, bool back)
1147 {
1148 	handleLineModeEnd();
1149 	QString tmpName = CommonStrings::None;
1150 	ScColor tmp;
1151 	ColorList::Iterator it;
1152 	quint16 Rc, Gc, Bc;
1153 	int redC, greenC, blueC;
1154 	ts >> Rc >> Gc >> Bc;
1155 	redC = qRound((Rc / 65535.0) * 255.0);
1156 	greenC = qRound((Gc / 65535.0) * 255.0);
1157 	blueC = qRound((Bc / 65535.0) * 255.0);
1158 	QColor c = QColor(redC, greenC, blueC);
1159 	tmp.setRgbColor(redC, greenC, blueC);
1160 	tmp.setSpotColor(false);
1161 	tmp.setRegistrationColor(false);
1162 	tmpName = "FromPict"+c.name();
1163 	QString fNam = m_Doc->PageColors.tryAddColor(tmpName, tmp);
1164 	if (fNam == tmpName)
1165 		importedColors.append(tmpName);
1166 	tmpName = fNam;
1167 	if (back)
1168 	{
1169 		CurrColorFill = tmpName;
1170 		backColor = c;
1171 	}
1172 	else
1173 	{
1174 		CurrColorStroke = tmpName;
1175 		foreColor = c;
1176 	}
1177 }
1178 
handlePenPattern(QDataStream & ts)1179 void PctPlug::handlePenPattern(QDataStream &ts)
1180 {
1181 	handleLineModeEnd();
1182 	patternData.resize(8);
1183 	ts.readRawData(patternData.data(), 8);
1184 	patternMode = false;
1185 	for (int a = 0; a < patternData.size(); a++)
1186 	{
1187 		uchar d = patternData[a];
1188 		if ((d != 0x00) && (d != 0xFF))
1189 		{
1190 			patternMode = true;
1191 			break;
1192 		}
1193 	}
1194 }
1195 
handlePolygon(QDataStream & ts,quint16 opCode)1196 void PctPlug::handlePolygon(QDataStream &ts, quint16 opCode)
1197 {
1198 //	qDebug() << "Handle Polygon";
1199 	handleLineModeEnd();
1200 	quint16 polySize;
1201 	ts >> polySize;				// read polygon size
1202 	ts.skipRawData(8);			// skip bounding rect;
1203 	polySize -= 14;				// subtract size count, bounding rect and first point from size
1204 	qint16 x, y;
1205 	ts >> y >> x;
1206 	Coords.resize(0);
1207 	Coords.svgInit();
1208 	PageItem *ite;
1209 	Coords.svgMoveTo(x * resX, y * resY);
1210 	for (unsigned i = 0; i < polySize; i += 4)
1211 	{
1212 		ts >> y >> x;
1213 		Coords.svgLineTo(x * resX, y * resX);
1214 	}
1215 	if (!Coords.empty())
1216 	{
1217 		int z;
1218 		if (opCode == 0x0070)
1219 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CommonStrings::None, CurrColorStroke);
1220 		else if (opCode == 0x0071)
1221 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorStroke, CommonStrings::None);
1222 //		else if (opCode == 0x0072)
1223 //			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CommonStrings::None);
1224 		else if (opCode == 0x0074)
1225 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorStroke, CommonStrings::None);
1226 		else
1227 		{
1228 //			qDebug() << QString("Not implemented OpCode: 0x%1").arg(opCode, 4, 16, QLatin1Char('0'));
1229 			return;
1230 		}
1231 		ite = m_Doc->Items->at(z);
1232 		ite->PoLine = Coords.copy();
1233 		ite->PoLine.translate(baseX, baseY);
1234 		ite->PoLine.translate(offsetX, offsetY);
1235 		finishItem(ite);
1236 		if ((patternMode) && (opCode != 0x0070))
1237 			setFillPattern(ite);
1238 	}
1239 }
1240 
handleShape(QDataStream & ts,quint16 opCode)1241 void PctPlug::handleShape(QDataStream &ts, quint16 opCode)
1242 {
1243 	handleLineModeEnd();
1244 	QRect bounds = readRect(ts);
1245 //	qDebug() << QString("Handle Rect/Oval 0x%1").arg(opCode, 4, 16, QLatin1Char('0'));
1246 	int z;
1247 	double xp = baseX + (bounds.x() * resX);
1248 	double yp = baseX + (bounds.y() * resY);
1249 	double wv = (bounds.width() - 1) * resX;
1250 	double hv = (bounds.height() - 1) * resY;
1251 	PageItem *ite;
1252 	if (opCode == 0x0030)
1253 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xp, yp, wv, hv, LineW, CommonStrings::None, CurrColorStroke);
1254 	else if (opCode == 0x0031)
1255 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xp, yp, wv, hv, 0, CurrColorStroke, CommonStrings::None);
1256 //	else if (opCode == 0x0032)
1257 //		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + bounds.x(), baseY + bounds.y(), bounds.width() - 1, bounds.height() - 1, 0, CurrColorFill, CommonStrings::None);
1258 	else if (opCode == 0x0034)
1259 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xp, yp, wv, hv, 0, CurrColorStroke, CommonStrings::None);
1260 	else if (opCode == 0x0040)
1261 	{
1262 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xp, yp, wv, hv, LineW, CommonStrings::None, CurrColorStroke);
1263 		ite = m_Doc->Items->at(z);
1264 		ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1265 		ite->SetFrameRound();
1266 		m_Doc->setRedrawBounding(ite);
1267 	}
1268 	else if (opCode == 0x0041)
1269 	{
1270 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xp, yp, wv, hv, 0, CurrColorStroke, CommonStrings::None);
1271 		ite = m_Doc->Items->at(z);
1272 		ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1273 		ite->SetFrameRound();
1274 		m_Doc->setRedrawBounding(ite);
1275 	}
1276 //	else if (opCode == 0x0042)
1277 //	{
1278 //		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + bounds.x(), baseY + bounds.y(), bounds.width() - 1, bounds.height() - 1, 0, CurrColorFill, CommonStrings::None);
1279 //		ite = m_Doc->Items->at(z);
1280 //		ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1281 //		ite->SetFrameRound();
1282 //		m_Doc->setRedrawBounding(ite);
1283 //	}
1284 	else if (opCode == 0x0044)
1285 	{
1286 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xp, yp, wv, hv, 0, CurrColorStroke, CommonStrings::None);
1287 		ite = m_Doc->Items->at(z);
1288 		ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1289 		ite->SetFrameRound();
1290 		m_Doc->setRedrawBounding(ite);
1291 	}
1292 	else if (opCode == 0x0050)
1293 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, xp, yp, wv, hv, LineW, CommonStrings::None, CurrColorStroke);
1294 	else if (opCode == 0x0051)
1295 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, xp, yp, wv, hv, 0, CurrColorStroke, CommonStrings::None);
1296 //	else if (opCode == 0x0052)
1297 //		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + bounds.x(), baseY + bounds.y(), bounds.width() - 1, bounds.height() - 1, 0, CurrColorFill, CommonStrings::None);
1298 	else if (opCode == 0x0054)
1299 		z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, xp, yp, wv, hv, 0, CurrColorStroke, CommonStrings::None);
1300 	else
1301 	{
1302 //		qDebug() << QString("Not implemented OpCode: 0x%1").arg(opCode, 4, 16, QLatin1Char('0'));
1303 		return;
1304 	}
1305 	ite = m_Doc->Items->at(z);
1306 	ite->PoLine.translate(offsetX, offsetY);
1307 	currRect = QRect(bounds.x() * resX, bounds.y() * resY, bounds.width() * resX, bounds.height() * resY);
1308 	currRectItemNr = z;
1309 	currRectType = 0;
1310 	if (opCode > 0x0044)
1311 		currRectType = 1;
1312 	finishItem(ite);
1313 	if ((patternMode) && (opCode != 0x0030) && (opCode != 0x0040) && (opCode != 0x0050))
1314 		setFillPattern(ite);
1315 }
1316 
handleSameShape(QDataStream & ts,quint16 opCode)1317 void PctPlug::handleSameShape(QDataStream &ts, quint16 opCode)
1318 {
1319 //	qDebug() << QString("Handle Same Rect/Oval 0x%1").arg(opCode, 4, 16, QLatin1Char('0'));
1320 	int rectType = 0;
1321 	if (opCode > 0x0050)
1322 		rectType = 1;
1323 	handleLineModeEnd();
1324 	int z;
1325 	PageItem *ite;
1326 	if (currRectType == rectType)
1327 	{
1328 		ite = m_Doc->Items->at(currRectItemNr);
1329 		if ((opCode == 0x0038) || (opCode == 0x0048) || (opCode == 0x0058))
1330 		{
1331 			ite->setLineColor(CurrColorStroke);
1332 			ite->setLineWidth(LineW);
1333 		}
1334 //		else if ((opCode == 0x003A) || (opCode == 0x004A) || (opCode == 0x005A))
1335 //			ite->setFillColor(CurrColorFill);
1336 		else
1337 			ite->setFillColor(CurrColorStroke);
1338 	}
1339 	else
1340 	{
1341 		if (opCode == 0x0038)
1342 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, LineW, CommonStrings::None, CurrColorStroke);
1343 		else if (opCode == 0x0039)
1344 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorStroke, CommonStrings::None);
1345 //		else if (opCode == 0x003A)
1346 //			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorFill, CommonStrings::None);
1347 		else if (opCode == 0x003C)
1348 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorStroke, CommonStrings::None);
1349 		else if (opCode == 0x0048)
1350 		{
1351 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CommonStrings::None, CurrColorStroke);
1352 			ite = m_Doc->Items->at(z);
1353 			ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1354 			ite->SetFrameRound();
1355 			m_Doc->setRedrawBounding(ite);
1356 		}
1357 		else if (opCode == 0x0049)
1358 		{
1359 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorStroke, CommonStrings::None);
1360 			ite = m_Doc->Items->at(z);
1361 			ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1362 			ite->SetFrameRound();
1363 			m_Doc->setRedrawBounding(ite);
1364 		}
1365 //		else if (opCode == 0x004A)
1366 //		{
1367 //			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorFill, CommonStrings::None);
1368 //			ite = m_Doc->Items->at(z);
1369 //			ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1370 //			ite->SetFrameRound();
1371 //			m_Doc->setRedrawBounding(ite);
1372 //		}
1373 		else if (opCode == 0x004C)
1374 		{
1375 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorStroke, CommonStrings::None);
1376 			ite = m_Doc->Items->at(z);
1377 			ite->setCornerRadius(qMax(ovalSize.x(), ovalSize.y()));
1378 			ite->SetFrameRound();
1379 			m_Doc->setRedrawBounding(ite);
1380 		}
1381 		else if (opCode == 0x0058)
1382 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, LineW, CommonStrings::None, CurrColorStroke);
1383 		else if (opCode == 0x0059)
1384 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorStroke, CommonStrings::None);
1385 //		else if (opCode == 0x005A)
1386 //			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorFill, CommonStrings::None);
1387 		else if (opCode == 0x005C)
1388 			z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + currRect.x(), baseY + currRect.y(), currRect.width() - 1, currRect.height() - 1, 0, CurrColorStroke, CommonStrings::None);
1389 		else
1390 		{
1391 //			qDebug() << QString("Not implemented OpCode: 0x%1").arg(opCode, 4, 16, QLatin1Char('0'));
1392 			return;
1393 		}
1394 		ite = m_Doc->Items->at(z);
1395 		ite->PoLine.translate(offsetX, offsetY);
1396 		finishItem(ite);
1397 	}
1398 	if ((patternMode) && (opCode != 0x0038) && (opCode != 0x0048) && (opCode != 0x0058))
1399 		setFillPattern(ite);
1400 }
1401 
handleFontName(QDataStream & ts)1402 void PctPlug::handleFontName(QDataStream &ts)
1403 {
1404 	handleLineModeEnd();
1405 	quint16 dataLen, fontID;
1406 	quint8 nameLen;
1407 	ts >> dataLen >> fontID;
1408 	ts >> nameLen;
1409 	QByteArray fontRawName;
1410 	fontRawName.resize(nameLen);
1411 	ts.readRawData(fontRawName.data(), nameLen);
1412 	QString fontName = fontRawName;
1413 	fontName = fontName.simplified();
1414 	SCFonts fonts = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts;
1415 	SCFontsIterator it(fonts);
1416 	for ( ; it.hasNext() ; it.next())
1417 	{
1418 
1419 		if (fonts[it.currentKey()].scName().simplified() == fontName)
1420 		{
1421 			fontName = fonts[it.currentKey()].family();
1422 			break;
1423 		}
1424 	}
1425 	fontMap.insert(fontID, fontName);
1426 	alignStreamToWord(ts, 0);
1427 //	qDebug() << "Handle FontName" << fontName << "ID" << fontID;
1428 }
1429 
handleTextSize(QDataStream & ts)1430 void PctPlug::handleTextSize(QDataStream &ts)
1431 {
1432 	handleLineModeEnd();
1433 	quint16 fontSize;
1434 	ts >> fontSize;
1435 	currentTextSize = fontSize * resY;
1436 //	qDebug() << "Handle Text Size" << fontSize;
1437 }
1438 
handleTextFont(QDataStream & ts)1439 void PctPlug::handleTextFont(QDataStream &ts)
1440 {
1441 	handleLineModeEnd();
1442 	quint16 fontID;
1443 	ts >> fontID;
1444 	currentFontID = fontID;
1445 //	qDebug() << "Handle Text Font" << fontID;
1446 }
1447 
handleTextStyle(QDataStream & ts)1448 void PctPlug::handleTextStyle(QDataStream &ts)
1449 {
1450 	handleLineModeEnd();
1451 	quint8 style;
1452 	ts >> style;
1453 	alignStreamToWord(ts, 0);
1454 	currentFontStyle = style;
1455 //	qDebug() << "Text Style" << style;
1456 }
1457 
handleLongText(QDataStream & ts)1458 void PctPlug::handleLongText(QDataStream &ts)
1459 {
1460 	handleLineModeEnd();
1461 	quint8 textLen;
1462 	qint16 x, y;
1463 	ts >> y >> x;
1464 	ts >> textLen;
1465 	QByteArray text;
1466 	text.resize(textLen);
1467 	ts.readRawData(text.data(), textLen);
1468 	if (!textIsPostScript)
1469 	{
1470 		currentPointT = QPoint(x * resX, y * resY);
1471 		createTextPath(text);
1472 //		qDebug() << "Handle Long Text at" << x << y << text;
1473 	}
1474 	alignStreamToWord(ts, 0);
1475 }
1476 
handleDHText(QDataStream & ts)1477 void PctPlug::handleDHText(QDataStream &ts)
1478 {
1479 	handleLineModeEnd();
1480 	quint8 textLen, dh;
1481 	ts >> dh >> textLen;
1482 	QByteArray text;
1483 	text.resize(textLen);
1484 	ts.readRawData(text.data(), textLen);
1485 	if (!textIsPostScript)
1486 	{
1487 		QPoint s = currentPointT;
1488 		currentPointT = QPoint(s.x()+dh * resX, s.y());
1489 		createTextPath(text);
1490 //		qDebug() << "Handle DH Text at" << currentPointT << text;
1491 	}
1492 	alignStreamToWord(ts, 0);
1493 }
1494 
handleDVText(QDataStream & ts)1495 void PctPlug::handleDVText(QDataStream &ts)
1496 {
1497 	handleLineModeEnd();
1498 	quint8 textLen, dv;
1499 	ts >> dv >> textLen;
1500 	QByteArray text;
1501 	text.resize(textLen);
1502 	ts.readRawData(text.data(), textLen);
1503 	if (!textIsPostScript)
1504 	{
1505 		QPoint s = currentPointT;
1506 		currentPointT = QPoint(s.x(), s.y()+dv * resY);
1507 		createTextPath(text);
1508 //		qDebug() << "Handle DV Text at" << currentPointT << text;
1509 	}
1510 	alignStreamToWord(ts, 0);
1511 }
1512 
handleDHVText(QDataStream & ts)1513 void PctPlug::handleDHVText(QDataStream &ts)
1514 {
1515 	handleLineModeEnd();
1516 	quint8 textLen, dv, dh;
1517 	ts >> dh >> dv >> textLen;
1518 	QByteArray text;
1519 	text.resize(textLen);
1520 	ts.readRawData(text.data(), textLen);
1521 	if (!textIsPostScript)
1522 	{
1523 		QPoint s = currentPointT;
1524 		currentPointT = QPoint(s.x()+dh * resX, s.y()+dv * resY);
1525 		createTextPath(text);
1526 //		qDebug() << "Handle DHV Text" << dh << dv << "->" << currentPointT << text;
1527 	}
1528 	alignStreamToWord(ts, 0);
1529 }
1530 
createTextPath(const QByteArray & textString)1531 void PctPlug::createTextPath(const QByteArray& textString)
1532 {
1533 	QTextCodec *codec = QTextCodec::codecForName("Apple Roman");
1534 	if (!codec)
1535 	{
1536 		codec = QTextCodec::codecForName("macroman");
1537 		if (!codec)
1538 			return;
1539 	}
1540 	QString string(codec->toUnicode(textString));
1541 	QFont textFont;
1542 	if (!fontMap.contains(currentFontID))
1543 		textFont = QFont();
1544 	else
1545 		textFont = QFont(fontMap[currentFontID], currentTextSize);
1546 	textFont.setPixelSize(currentTextSize);
1547 	if (currentFontStyle & 1)
1548 		textFont.setBold(true);
1549 	if (currentFontStyle & 2)
1550 		textFont.setItalic(true);
1551 	if (currentFontStyle & 4)
1552 		textFont.setUnderline(true);
1553 	FPointArray textPath;
1554 	QPainterPath painterPath;
1555 	painterPath.addText( currentPointT.x(), currentPointT.y(), textFont, string);
1556 	textPath.fromQPainterPath(painterPath);
1557 	if (!textPath.empty())
1558 	{
1559 		int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, CurrColorStroke, CommonStrings::None);
1560 		PageItem* ite = m_Doc->Items->at(z);
1561 		ite->PoLine = textPath;
1562 		ite->PoLine.translate(baseX, baseY);
1563 		ite->PoLine.translate(offsetX, offsetY);
1564 		finishItem(ite);
1565 		if (patternMode)
1566 			setFillPattern(ite);
1567 	}
1568 }
1569 
handlePenSize(QDataStream & ts)1570 void PctPlug::handlePenSize(QDataStream &ts)
1571 {
1572 //	qDebug() << "Handle Pen Size";
1573 	handleLineModeEnd();
1574 	quint16 x, y;
1575 	ts >> y >> x;
1576 	LineW = qMax(x, y) * resX;
1577 }
1578 
handleOvalSize(QDataStream & ts)1579 void PctPlug::handleOvalSize(QDataStream &ts)
1580 {
1581 //	qDebug() << "Handle Oval Size";
1582 	handleLineModeEnd();
1583 	quint16 x, y;
1584 	ts >> y >> x;
1585 	ovalSize = QPoint(x * resX, y * resY);
1586 }
1587 
handleShortLine(QDataStream & ts)1588 void PctPlug::handleShortLine(QDataStream &ts)
1589 {
1590 	quint16 x, y;
1591 	qint8 dh, dv;
1592 	ts >> y >> x;
1593 	ts >> dh >> dv;
1594 	if ((dh == 0) && (dv == 0))
1595 	{
1596 		handleLineModeEnd();
1597 		Coords.svgMoveTo(x * resX, y * resY);
1598 		currentPoint = QPoint(x * resX, y * resY);
1599 		return;
1600 	}
1601 	QPoint s = QPoint(x * resX, y * resY);
1602 	if (currentPoint != s)
1603 	{
1604 		handleLineModeEnd();
1605 		Coords.svgMoveTo(x * resX, y * resY);
1606 	}
1607 	Coords.svgLineTo((x+dh) * resX, (y+dv) * resY);
1608 	currentPoint = QPoint((x+dh) * resX, (y+dv) * resY);
1609 	lineMode = true;
1610 //	qDebug() << "Handle Short Line" << x << y << "+" << dh << dv << "->" << currentPoint;
1611 }
1612 
handleShortLineFrom(QDataStream & ts)1613 void PctPlug::handleShortLineFrom(QDataStream &ts)
1614 {
1615 	qint8 dh, dv;
1616 	ts >> dh >> dv;
1617 	if ((dh == 0) && (dv == 0))
1618 		return;
1619 	QPoint s = currentPoint;
1620 	if (Coords.empty())
1621 		Coords.svgMoveTo(s.x(), s.y());
1622 	Coords.svgLineTo(s.x()+dh * resX, s.y()+dv * resY);
1623 	currentPoint = QPoint(s.x()+dh * resX, s.y()+dv * resY);
1624 	lineMode = true;
1625 //	qDebug() << "Handle Short Line from" << dh << dv << "->" << currentPoint;
1626 }
1627 
handleLine(QDataStream & ts)1628 void PctPlug::handleLine(QDataStream &ts)
1629 {
1630 	qint16 x1, x2, y1, y2;
1631 	ts >> y1 >> x1;
1632 	ts >> y2 >> x2;
1633 	QPoint s = QPoint(x1 * resX, y1 * resY);
1634 	if (currentPoint != s)
1635 	{
1636 		handleLineModeEnd();
1637 		Coords.svgMoveTo(x1 * resX, y1 * resY);
1638 	}
1639 	Coords.svgLineTo(x2 * resX, y2 * resY);
1640 	currentPoint = QPoint(x2 * resX, y2 * resY);
1641 	lineMode = true;
1642 //	qDebug() << "Handle Line" << x1 << y1 << "->" << currentPoint;
1643 }
1644 
handleLineFrom(QDataStream & ts)1645 void PctPlug::handleLineFrom(QDataStream &ts)
1646 {
1647 	qint16 x, y;
1648 	ts >> y >> x;
1649 	if ((x == 0) && (y == 0))
1650 		return;
1651 	QPoint s = currentPoint;
1652 	if (Coords.empty())
1653 		Coords.svgMoveTo(s.x(), s.y());
1654 	Coords.svgLineTo(x * resX, y * resY);
1655 	currentPoint = QPoint(x * resX, y * resY);
1656 	lineMode = true;
1657 //	qDebug() << "Handle Line from" << s << "->" << currentPoint;
1658 }
1659 
handlePixmap(QDataStream & ts,quint16 opCode)1660 void PctPlug::handlePixmap(QDataStream &ts, quint16 opCode)
1661 {
1662 	handleLineModeEnd();
1663 	quint16 bytesPerLine = 0, packType = 0, pixel_type = 0, bits_per_pixel = 0, component_count = 0, component_size = 0;
1664 	quint32 packSize = 0, horizontal_resolution = 0, vertical_resolution = 0, color_table = 0, plane_bytes = 0;
1665 	if ((opCode == 0x009A) || (opCode == 0x009B))
1666 		ts.skipRawData(4);
1667 	ts >> bytesPerLine;
1668 	QRect bounds = readRect(ts);
1669 	bool isPixmap = bytesPerLine & 0x8000;
1670 	bytesPerLine &= 0x7FFF;
1671 //	qDebug() << "Bytes per Line" << bytesPerLine << "Pixmap" << isPixmap;
1672 //	qDebug() << "Bounds" << bounds.right() - bounds.left() << bounds.bottom() - bounds.top();
1673 	QVector<QRgb> colors;
1674 	if (isPixmap)
1675 	{
1676 		ts.skipRawData(2);	// skip Version info, always 0
1677 		ts >> packType;
1678 		ts >> packSize;
1679 		ts >> horizontal_resolution >> vertical_resolution;
1680 		ts >> pixel_type >> bits_per_pixel >> component_count >> component_size;
1681 		ts >> plane_bytes >> color_table;
1682 		ts.skipRawData(4);
1683 //		qDebug() << "Pack Type" << packType;
1684 //		qDebug() << "Pack Size" << packSize;
1685 //		qDebug() << "Pixel Type" << pixel_type;
1686 //		qDebug() << "Bits per Pixel" << bits_per_pixel;
1687 //		qDebug() << "Component Count" << component_count << "Size" << component_size;
1688 	// now reading color Table
1689 		if ((opCode != 0x009A) && (opCode != 0x009B))
1690 		{
1691 			quint32 ct_seed;
1692 			quint16 ct_flags, ct_size;
1693 			ts >> ct_seed;
1694 			ts >> ct_flags >> ct_size;
1695 //			qDebug() << "ColorTable has" << ct_size << "Entries";
1696 			colors.reserve(ct_size + 1);
1697 			for (quint16 cc = 0; cc < ct_size+1; cc++)
1698 			{
1699 				quint16 cev, cRed, cGreen, cBlue;
1700 				ts >> cev >> cRed >> cGreen >> cBlue;
1701 				colors.append(qRgb(cRed, cGreen, cBlue));
1702 			}
1703 		}
1704 	}
1705 // reading scrRect
1706 	QRect scrRect = readRect(ts);
1707 	Q_UNUSED(scrRect);
1708 //	qDebug() << "Src Rect" << scrRect;
1709 // reading dstRect
1710 	QRect dstRect = readRect(ts);
1711 //	qDebug() << "Dst Rect" << dstRect;
1712 	ts.skipRawData(2);
1713 	if ((opCode == 0x0091) || (opCode == 0x0099) || (opCode == 0x009B))
1714 	{
1715 		quint16 dataLen;
1716 		ts >> dataLen;
1717 		alignStreamToWord(ts, dataLen-2);
1718 	}
1719 	quint16 pixRows = bounds.bottom() - bounds.top();
1720 	quint16 pixCols = bounds.right() - bounds.left();
1721 	quint16 imgRows = dstRect.bottom() - dstRect.top();
1722 	quint16 imgCols = dstRect.right() - dstRect.left();
1723 	QImage image;
1724 	if (isPixmap)
1725 	{
1726 		if (component_count == 1)
1727 		{
1728 			image = QImage(pixCols, pixRows, QImage::Format_Indexed8);
1729 			image.setColorTable(colors);
1730 		}
1731 		else
1732 			image = QImage(pixCols, pixRows, QImage::Format_ARGB32);
1733 	}
1734 	else
1735 		image = QImage(pixCols, pixRows, QImage::Format_Mono);
1736 	for (quint16 rr = 0; rr < pixRows; rr++)
1737 	{
1738 		quint16 pixByteCount;
1739 		if (bytesPerLine < 250)
1740 		{
1741 			quint8 byteCount;
1742 			ts >> byteCount;
1743 			pixByteCount = byteCount;
1744 		}
1745 		else
1746 			ts >> pixByteCount;
1747 		if (!skipOpcode)
1748 		{
1749 			QByteArray data;
1750 			data.resize(pixByteCount);
1751 			ts.readRawData(data.data(), pixByteCount);
1752 			int twoByte = 1;
1753 			if (component_size == 5)
1754 				twoByte = 2;
1755 			QByteArray img;
1756 			if (bytesPerLine < 8)
1757 				img = data;
1758 			else
1759 				img = decodeRLE(data, bytesPerLine, twoByte);
1760 			if ((opCode == 0x0098) || (opCode == 0x0099))
1761 			{
1762 				if (!isPixmap)
1763 				{
1764 					memcpy(image.scanLine(rr), img.data(), bytesPerLine);
1765 				}
1766 				else if (component_count == 1)
1767 				{
1768 					if (component_size == 4)
1769 					{
1770 						uchar *q = (uchar*)(image.scanLine(rr));
1771 						for (int xx = 0; xx < img.size(); xx++)
1772 						{
1773 							uchar i = (img[xx] >> 4) & 0x0F;
1774 							uchar j = img[xx] & 0x0F;
1775 							*q++ = i;
1776 							*q++ = j;
1777 						}
1778 					}
1779 					else
1780 						memcpy(image.scanLine(rr), img.data(), bytesPerLine);
1781 				}
1782 			}
1783 			else if ((opCode == 0x009A) || (opCode == 0x009B))
1784 			{
1785 				if (component_size == 5)
1786 				{
1787 					QRgb *q = (QRgb*)(image.scanLine(rr));
1788 					int imgDcount = 0;
1789 					for (quint16 xx = 0; xx < pixCols; xx++)
1790 					{
1791 						uchar i = img[imgDcount++];
1792 						uchar j = img[imgDcount++];
1793 						quint16 r = (i & 0x7c) << 1;
1794 						quint16 g = ((i & 0x03) << 6) | ((j & 0xe0) >> 2);
1795 						quint16 b = (j & 0x1f) << 3;
1796 						*q++ = qRgba(r, g, b, 255);
1797 					}
1798 				}
1799 				else if ((component_size == 8) || (component_size == 24))
1800 				{
1801 					QRgb *q = (QRgb*)(image.scanLine(rr));
1802 					for (uint xx = 0; xx < (uint) pixCols; xx++)
1803 					{
1804 						uchar r = 0;
1805 						uchar g = 0;
1806 						uchar b = 0;
1807 						uchar a = 255;
1808 						if (component_count == 3)
1809 						{
1810 							r = img[xx];
1811 							g = img[xx + pixCols];
1812 							b = img[xx + 2 * pixCols];
1813 						}
1814 						else if (component_count == 4)
1815 						{
1816 							a = 255 - img[xx];
1817 							r = img[xx + pixCols];
1818 							g = img[xx + 2 * pixCols];
1819 							b = img[xx + 3 * pixCols];
1820 						}
1821 						*q++ = qRgba(r, g, b, a);
1822 					}
1823 				}
1824 			}
1825 		}
1826 		else
1827 		{
1828 			ts.skipRawData(pixByteCount);
1829 		}
1830 	}
1831 	if (skipOpcode)
1832 	{
1833 		image.loadFromData(imageData);
1834 		isPixmap = true;
1835 		imageData.resize(0);
1836 	}
1837 	if ((component_size == 24) || (component_size == 8) || (component_size == 1) || (component_size == 5) || (component_size == 4) || (!isPixmap) || (skipOpcode))
1838 	{
1839 		image = image.convertToFormat(QImage::Format_ARGB32);
1840 		if (!isPixmap)
1841 			image.invertPixels();
1842 		int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX + dstRect.left() * resX, baseY + dstRect.top() * resY, imgCols * resY, imgRows * resY, 0, m_Doc->itemToolPrefs().imageFillColor, m_Doc->itemToolPrefs().imageStrokeColor);
1843 		PageItem *ite = m_Doc->Items->at(z);
1844 		QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pct_XXXXXX.png");
1845 		tempFile->setAutoRemove(false);
1846 		tempFile->open();
1847 		QString fileName = getLongPathName(tempFile->fileName());
1848 		tempFile->close();
1849 		delete tempFile;
1850 		ite->isInlineImage = true;
1851 		ite->isTempFile = true;
1852 		image.save(fileName, "PNG");
1853 		ite->moveBy(baseX, baseY);
1854 		ite->moveBy(offsetX, offsetY);
1855 		finishItem(ite);
1856 		m_Doc->loadPict(fileName, ite);
1857 		ite->setImageScalingMode(false, false);
1858 		skipOpcode = false;
1859 	}
1860 	alignStreamToWord(ts, 0);
1861 }
1862 
handleQuickTime(QDataStream & ts,quint16 opCode)1863 void PctPlug::handleQuickTime(QDataStream &ts, quint16 opCode)
1864 {
1865 //	qDebug() << "Handle QuickTime Data";
1866 	quint32 dataLenLong, matteSize, maskSize, dataLen;
1867 	quint16 mode;
1868 	ts >> dataLenLong;
1869 	uint pos = ts.device()->pos();
1870 	handleLineModeEnd();
1871 	alignStreamToWord(ts, 38);		// Skip version and Matrix information
1872 	ts >> matteSize;
1873 	/*QRect matteRect =*/ readRect(ts);
1874 	if (opCode == 0x8200)
1875 	{
1876 		ts >> mode;
1877 		/*QRect srcRect =*/ readRect(ts);
1878 		alignStreamToWord(ts, 4);
1879 		ts >> maskSize;
1880 		if (matteSize != 0)
1881 		{
1882 			ts >> dataLen;
1883 			alignStreamToWord(ts, dataLen);
1884 			alignStreamToWord(ts, matteSize);
1885 		}
1886 		if (maskSize != 0)
1887 		{
1888 			ts >> dataLen;
1889 			alignStreamToWord(ts, dataLen);
1890 			alignStreamToWord(ts, maskSize);
1891 		}
1892 		quint32 cType, vendor, dummyLong, imgDataSize;
1893 		quint16 width, height, dummyShort;
1894 		ts >> dataLen;
1895 		ts >> cType;
1896 		if (cType == 0x6A706567)
1897 		{
1898 			ts >> dummyLong;
1899 			ts >> dummyShort;
1900 			ts >> dummyShort;
1901 			ts >> dummyShort;
1902 			ts >> dummyShort;
1903 			ts >> vendor;
1904 			ts >> dummyLong;
1905 			ts >> dummyLong;
1906 			ts >> width;
1907 			ts >> height;
1908 			ts >> dummyLong;
1909 			ts >> dummyLong;
1910 			ts >> imgDataSize;
1911 			alignStreamToWord(ts, 38);
1912 			imageData.resize(imgDataSize);
1913 			ts.readRawData(imageData.data(), imgDataSize);
1914 			skipOpcode = true;
1915 		}
1916 	}
1917 	else
1918 	{
1919 		if (matteSize != 0)
1920 		{
1921 			ts >> dataLen;
1922 			alignStreamToWord(ts, dataLen);
1923 			alignStreamToWord(ts, matteSize);
1924 		}
1925 		ts >> mode;
1926 		handlePixmap(ts, mode);
1927 		skipOpcode = true;
1928 	}
1929 	ts.device()->seek(pos + dataLenLong);
1930 //	qDebug() << "File Pos" << ts.device()->pos();
1931 }
1932 
handleComment(QDataStream & ts,bool longComment)1933 void PctPlug::handleComment(QDataStream &ts, bool longComment)
1934 {
1935 	quint16 commentCode;
1936 	handleLineModeEnd();
1937 	ts >> commentCode;
1938 	switch (commentCode)
1939 	{
1940 		case 100:			// picAppComment
1941 //			qDebug() << "Comment type: picAppComment";
1942 			break;
1943 		case 130:			// picDwgBeg
1944 //			qDebug() << "Comment type: picDwgBeg";
1945 			break;
1946 		case 131:			// picDwgEnd
1947 //			qDebug() << "Comment type: picDwgEnd";
1948 			break;
1949 		case 140:			// picGrpBeg
1950 //			qDebug() << "Comment type: picGrpBeg";
1951 			break;
1952 		case 141:			// picGrpEnd
1953 //			qDebug() << "Comment type: picGrpEnd";
1954 			break;
1955 		case 142:			// picBitBeg
1956 //			qDebug() << "Comment type: picBitBeg";
1957 			break;
1958 		case 143:			// picBitEnd
1959 //			qDebug() << "Comment type: picBitEnd";
1960 			break;
1961 		case 150:			// TextBegin
1962 //			qDebug() << "Comment type: TextBegin";
1963 			break;
1964 		case 151:			// TextEnd
1965 //			qDebug() << "Comment type: TextEnd";
1966 			break;
1967 		case 152:			// StringBegin
1968 //			qDebug() << "Comment type: StringBegin";
1969 			break;
1970 		case 153:			// StringEnd
1971 //			qDebug() << "Comment type: StringEnd";
1972 			break;
1973 		case 154:			// TextCenter
1974 //			qDebug() << "Comment type: TextCenter";
1975 			break;
1976 		case 155:			// LineLayoutOff
1977 //			qDebug() << "Comment type: LineLayoutOff";
1978 			break;
1979 		case 156:			// LineLayoutOn
1980 //			qDebug() << "Comment type: LineLayoutOn";
1981 			break;
1982 		case 157:			// ClientLineLayout
1983 //			qDebug() << "Comment type: ClientLineLayout";
1984 			break;
1985 		case 160:			// PolyBegin
1986 //			qDebug() << "Comment type: PolyBegin";
1987 			break;
1988 		case 161:			// PolyEnd
1989 //			qDebug() << "Comment type: PolyEnd";
1990 			break;
1991 		case 163:			// PolyIgnore
1992 //			qDebug() << "Comment type: PolyIgnore";
1993 			break;
1994 		case 164:			// PolySmooth
1995 //			qDebug() << "Comment type: PolySmooth";
1996 			break;
1997 		case 165:			// PolyClose
1998 //			qDebug() << "Comment type: PolyClose";
1999 			break;
2000 		case 170:			// picArrw1 Arrowhead on 2nd point of line
2001 //			qDebug() << "Comment type: picArrw1";
2002 			break;
2003 		case 171:			// picArrw2 Arrowhead on 1nd point of line
2004 //			qDebug() << "Comment type: picArrw2";
2005 			break;
2006 		case 172:			// picArrw3 Arrowhead on both endpoints
2007 //			qDebug() << "Comment type: picArrw3";
2008 			break;
2009 		case 173:			// picArrwEnd End of arrowhead comment
2010 //			qDebug() << "Comment type: picArrwEnd";
2011 			break;
2012 		case 180:			// DashedLine
2013 //			qDebug() << "Comment type: DashedLine";
2014 			break;
2015 		case 181:			// DashedStop
2016 //			qDebug() << "Comment type: DashedStop";
2017 			break;
2018 		case 182:			// SetLineWidth
2019 //			qDebug() << "Comment type: SetLineWidth";
2020 			break;
2021 		case 190:			// PostScriptBegin
2022 			postscriptMode = true;
2023 //			qDebug() << "Comment type: PostScriptBegin";
2024 			break;
2025 		case 191:			// PostScriptEnd
2026 			postscriptMode = false;
2027 			textIsPostScript = false;
2028 //			qDebug() << "Comment type: PostScriptEnd";
2029 			break;
2030 		case 192:			// PostScriptHandle
2031 //			qDebug() << "Comment type: PostScriptHandle";
2032 			break;
2033 		case 193:			// PostScriptFile
2034 //			qDebug() << "Comment type: PostScriptFile";
2035 			break;
2036 		case 194:			// TextIsPostScript
2037 			textIsPostScript = true;
2038 //			qDebug() << "Comment type: TextIsPostScript";
2039 			break;
2040 		case 195:			// ResourcePS
2041 //			qDebug() << "Comment type: ResourcePS";
2042 			break;
2043 		case 196:			// PSBeginNoSave
2044 //			qDebug() << "Comment type: PSBeginNoSave";
2045 			break;
2046 		case 200:			// RotateBegin
2047 //			qDebug() << "Comment type: RotateBegin";
2048 			break;
2049 		case 201:			// RotateEnd
2050 //			qDebug() << "Comment type: RotateEnd";
2051 			break;
2052 		case 210:			// FormsPrinting
2053 //			qDebug() << "Comment type: FormsPrinting";
2054 			break;
2055 		case 211:			// EndFormsPrinting
2056 //			qDebug() << "Comment type: EndFormsPrinting";
2057 			break;
2058 		case 220:			// CMBeginProfile
2059 //			qDebug() << "Comment type: CMBeginProfile";
2060 			break;
2061 		case 221:			// CMEndProfile
2062 //			qDebug() << "Comment type: CMEndProfile";
2063 			break;
2064 		case 222:			// CMEnableMatching
2065 //			qDebug() << "Comment type: CMEnableMatching";
2066 			break;
2067 		case 223:			// CMDisableMatching
2068 //			qDebug() << "Comment type: CMDisableMatching";
2069 			break;
2070 		default:
2071 //			qDebug() << "Unknown Pict-Comment" << commentCode;
2072 			break;
2073 	}
2074 	if (longComment)
2075 	{
2076 		quint16 dataLen;
2077 		ts >> dataLen;
2078 		alignStreamToWord(ts, dataLen);
2079 	}
2080 }
2081 
readRect(QDataStream & ts)2082 QRect PctPlug::readRect(QDataStream &ts)
2083 {
2084 	qint16 RectX, RectY, RectW, RectH;
2085 	ts >> RectX >> RectY >> RectW >> RectH;
2086 	return QRect(QPoint(RectY, RectX), QPoint(RectH, RectW));
2087 }
2088 
decodeRLE(QByteArray & in,quint16 bytesPerLine,int twoByte)2089 QByteArray PctPlug::decodeRLE(QByteArray &in, quint16 bytesPerLine, int twoByte)
2090 {
2091 	QByteArray ret = QByteArray(bytesPerLine, ' ');
2092 	uchar *ptrOut, *ptrIn;
2093 	ptrOut = (uchar*)ret.data();
2094 	ptrIn = (uchar*)in.data();
2095 	quint16 count = 0;
2096 	uchar c, c2;
2097 	quint16 len;
2098 	while (count < in.size())
2099 	{
2100 		c = *ptrIn++;
2101 		count++;
2102 		len = c;
2103 		if (len < 128)
2104 		{
2105 			// Copy next len+1 bytes literally.
2106 			len++;
2107 			len *= twoByte;
2108 			while (len != 0)
2109 			{
2110 				*ptrOut++ = *ptrIn++;
2111 				len--;
2112 				count++;
2113 				if (twoByte == 2)
2114 				{
2115 					*ptrOut++ = *ptrIn++;
2116 					len--;
2117 					count++;
2118 				}
2119 			}
2120 		}
2121 		else if (len > 128)
2122 		{
2123 			// Next -len+1 bytes in the dest are replicated from next source byte.
2124 			// (Interpret len as a negative 8-bit int.)
2125 			len ^= 0xFF;
2126 			len += 2;
2127 			len *= twoByte;
2128 			if (twoByte == 2)
2129 			{
2130 				c = *ptrIn++;
2131 				count++;
2132 				c2 = *ptrIn++;
2133 				count++;
2134 				while (len != 0)
2135 				{
2136 					*ptrOut++ = c;
2137 					*ptrOut++ = c2;
2138 					len--;
2139 					len--;
2140 				}
2141 			}
2142 			else
2143 			{
2144 				c = *ptrIn++;
2145 				count++;
2146 				while (len != 0)
2147 				{
2148 					*ptrOut++ = c;
2149 					len--;
2150 				}
2151 			}
2152 		}
2153 		else if (len == 128)
2154 		{
2155 			// No-op.
2156 		}
2157 	}
2158 	return ret;
2159 }
2160 
setFillPattern(PageItem * ite)2161 void PctPlug::setFillPattern(PageItem* ite)
2162 {
2163 	uint oldNum = m_Doc->TotalItems;
2164 	QString patternName;
2165 	quint32 patDat1, patDat2;
2166 	QDataStream bu(&patternData, QIODevice::ReadOnly);
2167 	bu >> patDat1 >> patDat2;
2168 	QString patNa = QString("%1%2%3%4").arg(backColor.name(), foreColor.name()).arg(patDat1, 8, 16, QLatin1Char('0')).arg(patDat2, 8, 16, QLatin1Char('0'));
2169 	if (!patternMap.contains(patNa))
2170 	{
2171 		QImage image = QImage(8, 8, QImage::Format_Mono);
2172 		QVector<QRgb> colors;
2173 		colors.append(backColor.rgb());
2174 		colors.append(foreColor.rgb());
2175 		image.setColorTable(colors);
2176 		for (int rr = 0; rr < 8; rr++)
2177 		{
2178 			uchar *q = (uchar*)(image.scanLine(rr));
2179 			*q = patternData[rr];
2180 		}
2181 		image = image.convertToFormat(QImage::Format_ARGB32);
2182 		ScPattern pat = ScPattern();
2183 		pat.setDoc(m_Doc);
2184 		PageItem* newItem = new PageItem_ImageFrame(m_Doc, 0, 0, 1, 1, 0, CommonStrings::None, CommonStrings::None);
2185 		QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pct_XXXXXX.png");
2186 		tempFile->setAutoRemove(false);
2187 		tempFile->open();
2188 		QString fileName = getLongPathName(tempFile->fileName());
2189 		tempFile->close();
2190 		delete tempFile;
2191 		newItem->isInlineImage = true;
2192 		newItem->isTempFile = true;
2193 		image.setDotsPerMeterY(2834);
2194 		image.setDotsPerMeterX(2834);
2195 		image.save(fileName, "PNG");
2196 		if (newItem->loadImage(fileName, false, 72, false))
2197 		{
2198 			pat.width = image.width();
2199 			pat.height = image.height();
2200 			pat.scaleX = (72.0 / newItem->pixm.imgInfo.xres) * newItem->pixm.imgInfo.lowResScale;
2201 			pat.scaleY = (72.0 / newItem->pixm.imgInfo.xres) * newItem->pixm.imgInfo.lowResScale;
2202 			pat.pattern = newItem->pixm.qImage().copy();
2203 			newItem->setWidth(pat.pattern.width());
2204 			newItem->setHeight(pat.pattern.height());
2205 			newItem->SetRectFrame();
2206 			newItem->gXpos = 0.0;
2207 			newItem->gYpos = 0.0;
2208 			newItem->gWidth = pat.pattern.width();
2209 			newItem->gHeight = pat.pattern.height();
2210 			pat.items.append(newItem);
2211 		}
2212 		patternName = "Pattern_"+newItem->itemName();
2213 		patternName = patternName.trimmed().simplified().replace(" ", "_");
2214 		m_Doc->addPattern(patternName, pat);
2215 		importedPatterns.append(patternName);
2216 		patternMap.insert(patNa, patternName);
2217 	}
2218 	else
2219 		patternName = patternMap[patNa];
2220 	ite->setPattern(patternName);
2221 	ite->GrType = Gradient_Pattern;
2222 	m_Doc->TotalItems = oldNum;
2223 //	qDebug() << "Using Pattern" << patternName << "internal Name" << patNa;
2224 }
2225 
handleLineModeEnd()2226 void PctPlug::handleLineModeEnd()
2227 {
2228 	if ((Coords.size() > 3) && lineMode)
2229 	{
2230 		int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CommonStrings::None, CurrColorStroke);
2231 		PageItem *ite = m_Doc->Items->at(z);
2232 		ite->PoLine = Coords.copy();
2233 		ite->PoLine.translate(offsetX, offsetY);
2234 		finishItem(ite);
2235 	}
2236 	Coords.resize(0);
2237 	Coords.svgInit();
2238 	lineMode = false;
2239 }
2240 
finishItem(PageItem * ite)2241 void PctPlug::finishItem(PageItem* ite)
2242 {
2243 	ite->ClipEdited = true;
2244 	ite->FrameType = 3;
2245 	ite->setFillShade(CurrFillShade);
2246 	ite->setLineShade(CurrStrokeShade);
2247 	FPoint wh = getMaxClipF(&ite->PoLine);
2248 	ite->setWidthHeight(wh.x(),wh.y());
2249 	ite->setTextFlowMode(PageItem::TextFlowDisabled);
2250 	m_Doc->adjustItemSize(ite);
2251 	ite->OldB2 = ite->width();
2252 	ite->OldH2 = ite->height();
2253 	ite->updateClip();
2254 	Elements.append(ite);
2255 	lastCoords = Coords;
2256 	Coords.resize(0);
2257 	Coords.svgInit();
2258 }
2259