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 <QDataStream>
11 #include <QDrag>
12 #include <QFile>
13 #include <QList>
14 #include <QMimeData>
15 #include <QRegExp>
16 #include <QStack>
17 #include <QTemporaryFile>
18 #include <QDebug>
19 
20 #include <cstdlib>
21 #include <tiffio.h>
22 #include <zlib.h>
23 
24 #include "importai.h"
25 
26 #include "commonstrings.h"
27 #include "loadsaveplugin.h"
28 #include "prefscontext.h"
29 #include "prefsfile.h"
30 #include "prefsmanager.h"
31 #include "prefstable.h"
32 #include "qtiocompressor.h"
33 #include "rawimage.h"
34 #include "scclocale.h"
35 #include "sccolorengine.h"
36 #include "scconfig.h"
37 #include "scmimedata.h"
38 #include "scpaths.h"
39 #include "scpattern.h"
40 #include "scribusXml.h"
41 #include "scribuscore.h"
42 #include "scribusdoc.h"
43 #include "scribusview.h"
44 #include "sctextstream.h"
45 #include "selection.h"
46 #include "text/specialchars.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_color.h"
54 #include "util_file.h"
55 #include "util_formats.h"
56 #include "util_ghostscript.h"
57 #include "util_math.h"
58 
59 #include <cairo.h>
60 
61 #ifdef HAVE_PODOFO
62 	#include <podofo/podofo.h>
63 #endif
64 
AIPlug(ScribusDoc * doc,int flags)65 AIPlug::AIPlug(ScribusDoc* doc, int flags)
66 {
67 	tmpSel = new Selection(this, false);
68 	m_Doc = doc;
69 	importerFlags = flags;
70 	interactive = (flags & LoadSavePlugin::lfInteractive);
71 }
72 
readThumbnail(const QString & fNameIn)73 QImage AIPlug::readThumbnail(const QString& fNameIn)
74 {
75 	QString fName = fNameIn;
76 	double x, y, b, h;
77 	CustColors.clear();
78 	importedColors.clear();
79 	importedGradients.clear();
80 	importedPatterns.clear();
81 	QFileInfo fi = QFileInfo(fName);
82 /* Check if the file is an old style AI or one of the newer PDF wrapped ones */
83 	QFile fT(fName);
84 	if (fT.open(QIODevice::ReadOnly))
85 	{
86 		QByteArray tempBuf(9, ' ');
87 		fT.read(tempBuf.data(), 8);
88 		fT.close();
89 		if (tempBuf.startsWith("%PDF"))
90 		{
91 			QString tmp;
92 			QString pdfFile = QDir::toNativeSeparators(fName);
93 			QString tmpFile = QDir::toNativeSeparators(ScPaths::tempFileDir() + "sc.png");
94 			int ret = -1;
95 			tmp.setNum(1);
96 			QStringList args;
97 			args.append("-r72");
98 			args.append("-sOutputFile="+tmpFile);
99 			args.append("-dFirstPage="+tmp);
100 			args.append("-dLastPage="+tmp);
101 			args.append(pdfFile);
102 			ret = callGS(args);
103 			if (ret == 0)
104 			{
105 				QImage image;
106 				image.load(tmpFile);
107 				QFile::remove(tmpFile);
108 				image.setText("XSize", QString("%1").arg(image.width()));
109 				image.setText("YSize", QString("%1").arg(image.height()));
110 				return image;
111 			}
112 			return QImage();
113 		}
114 	}
115 	QFile fT2(fName);
116 	if (fT2.open(QIODevice::ReadOnly))
117 	{
118 		QByteArray tempBuf(25, ' ');
119 		fT2.read(tempBuf.data(), 20);
120 		fT2.close();
121 		/* Illustrator CS files might be compressed
122 			the compressed Data starts right after the "%AI12_CompressedData" comment
123 			Compression is a simple zlib compression */
124 		if (tempBuf.startsWith("%AI12_CompressedData"))
125 			decompressAIData(fName);
126 	}
127 	progressDialog = nullptr;
128 /* Set default Page to size defined in Preferences */
129 	x = 0.0;
130 	y = 0.0;
131 	b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
132 	h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
133 	parseHeader(fName, x, y, b, h);
134 	if (b == 0)
135 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
136 	if (h == 0)
137 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
138 	docX = x;
139 	docY = y;
140 	docWidth = b - x;
141 	docHeight = h - y;
142 	baseX = 0;
143 	baseY = 0;
144 	m_Doc = new ScribusDoc();
145 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
146 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
147 	m_Doc->addPage(0);
148 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
149 	baseX = m_Doc->currentPage()->xOffset();
150 	baseY = m_Doc->currentPage()->yOffset();
151 	ColorList::Iterator it;
152 	for (it = CustColors.begin(); it != CustColors.end(); ++it)
153 	{
154 		if (!m_Doc->PageColors.contains(it.key()))
155 		{
156 			m_Doc->PageColors.insert(it.key(), it.value());
157 			importedColors.append(it.key());
158 		}
159 	}
160 	Elements.clear();
161 	m_Doc->setLoading(true);
162 	m_Doc->DoDrawing = false;
163 	m_Doc->scMW()->setScriptRunning(true);
164 	QString CurDirP = QDir::currentPath();
165 	QDir::setCurrent(fi.path());
166 	QImage tmpImage;
167 	if (convert(fName))
168 	{
169 		tmpSel->clear();
170 		QDir::setCurrent(CurDirP);
171 		if (Elements.count() > 1)
172 			m_Doc->groupObjectsList(Elements);
173 		m_Doc->DoDrawing = true;
174 		m_Doc->m_Selection->delaySignalsOn();
175 		for (int dre=0; dre<Elements.count(); ++dre)
176 		{
177 			tmpSel->addItem(Elements.at(dre), true);
178 		}
179 		tmpSel->setGroupRect();
180 		double xs = tmpSel->width();
181 		double ys = tmpSel->height();
182 		if (Elements.count() > 0)
183 			tmpImage = Elements.at(0)->DrawObj_toImage(500);
184 		tmpImage.setText("XSize", QString("%1").arg(xs));
185 		tmpImage.setText("YSize", QString("%1").arg(ys));
186 		m_Doc->m_Selection->delaySignalsOff();
187 	}
188 	else
189 		tmpImage = QImage();
190 	m_Doc->scMW()->setScriptRunning(false);
191 	m_Doc->setLoading(false);
192 	delete m_Doc;
193 	QDir::setCurrent(CurDirP);
194 	return tmpImage;
195 }
196 
readColors(const QString & fileName,ColorList & colors)197 bool AIPlug::readColors(const QString& fileName, ColorList & colors)
198 {
199 	QString fName(fileName);
200 	bool success = false;
201 	cancel = false;
202 	double x, y, b, h;
203 	convertedPDF = false;
204 	CustColors.clear();
205 	importedColors.clear();
206 	importedGradients.clear();
207 	importedPatterns.clear();
208 	QFileInfo fi = QFileInfo(fName);
209 /* Check if the file is an old style AI or one of the newer PDF wrapped ones */
210 	QFile fT(fName);
211 	if (fT.open(QIODevice::ReadOnly))
212 	{
213 		QByteArray tempBuf(9, ' ');
214 		fT.read(tempBuf.data(), 8);
215 		fT.close();
216 		if (tempBuf.startsWith("%PDF"))
217 		{
218 			QFileInfo bF2(fName);
219 			QString tmpFile = ScPaths::tempFileDir()+ "/"+bF2.baseName()+"_tmp.ai";
220 			if (!extractFromPDF(fName, tmpFile))
221 				return false;
222 			convertedPDF = true;
223 			fName = tmpFile;
224 		}
225 	}
226 	QFile fT2(fName);
227 	if (fT2.open(QIODevice::ReadOnly))
228 	{
229 		QByteArray tempBuf(25, ' ');
230 		fT2.read(tempBuf.data(), 20);
231 		fT2.close();
232 		/* Illustrator CS files might be compressed
233 			the compressed Data starts right after the "%AI12_CompressedData" comment
234 			Compression is a simple zlib compression */
235 		if (tempBuf.startsWith("%AI12_CompressedData"))
236 			decompressAIData(fName);
237 	}
238 	progressDialog = nullptr;
239 /* Set default Page to size defined in Preferences */
240 	x = 0.0;
241 	y = 0.0;
242 	b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
243 	h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
244 	parseHeader(fName, x, y, b, h);
245 	docX = x;
246 	docY = y;
247 	docWidth = b - x;
248 	docHeight = h - y;
249 	m_Doc = new ScribusDoc();
250 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
251 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
252 	m_Doc->addPage(0);
253 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
254 	baseX = m_Doc->currentPage()->xOffset();
255 	baseY = m_Doc->currentPage()->yOffset();
256 	ColorList::Iterator it;
257 	for (it = CustColors.begin(); it != CustColors.end(); ++it)
258 	{
259 		if (!m_Doc->PageColors.contains(it.key()))
260 		{
261 			m_Doc->PageColors.insert(it.key(), it.value());
262 			importedColors.append(it.key());
263 		}
264 	}
265 	Elements.clear();
266 	m_Doc->setLoading(true);
267 	m_Doc->DoDrawing = false;
268 	m_Doc->scMW()->setScriptRunning(true);
269 	QString CurDirP = QDir::currentPath();
270 	QDir::setCurrent(fi.path());
271 	convert(fName);
272 	if (importedColors.count() != 0)
273 	{
274 		colors = m_Doc->PageColors;
275 		success = true;
276 	}
277 	m_Doc->scMW()->setScriptRunning(false);
278 	m_Doc->setLoading(false);
279 	delete m_Doc;
280 	QDir::setCurrent(CurDirP);
281 	if (convertedPDF)
282 		QFile::remove(fName);
283 	return success;
284 }
285 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)286 bool AIPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
287 {
288 	QString fName = fNameIn;
289 	bool success = false;
290 	interactive = (flags & LoadSavePlugin::lfInteractive);
291 	importerFlags = flags;
292 	cancel = false;
293 	double x, y, b, h;
294 	bool ret = false;
295 	convertedPDF = false;
296 	CustColors.clear();
297 	importedColors.clear();
298 	importedGradients.clear();
299 	importedPatterns.clear();
300 	QFileInfo fi = QFileInfo(fName);
301 //	QString ext = fi.suffix().toLower();
302 	if ( !ScCore->usingGUI() )
303 	{
304 		interactive = false;
305 		showProgress = false;
306 	}
307 
308 /* Check if the file is an old style AI or one of the newer PDF wrapped ones */
309 	QFile fT(fName);
310 	if (fT.open(QIODevice::ReadOnly))
311 	{
312 		QByteArray tempBuf(9, ' ');
313 		fT.read(tempBuf.data(), 8);
314 		fT.close();
315 		if (tempBuf.startsWith("%PDF"))
316 		{
317 			QFileInfo bF2(fName);
318 			QString tmpFile = ScPaths::tempFileDir()+ "/"+bF2.baseName()+"_tmp.ai";
319 			if (!extractFromPDF(fName, tmpFile))
320 				return false;
321 			convertedPDF = true;
322 			fName = tmpFile;
323 		}
324 	}
325 	QFile fT2(fName);
326 	if (fT2.open(QIODevice::ReadOnly))
327 	{
328 		QByteArray tempBuf(25, ' ');
329 		fT2.read(tempBuf.data(), 20);
330 		fT2.close();
331 		/* Illustrator CS files might be compressed
332 			the compressed Data starts right after the "%AI12_CompressedData" comment
333 			Compression is a simple zlib compression */
334 		if (tempBuf.startsWith("%AI12_CompressedData"))
335 			decompressAIData(fName);
336 	}
337 	if ( showProgress )
338 	{
339 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
340 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
341 		QStringList barNames, barTexts;
342 		barNames << "GI";
343 		barTexts << tr("Analyzing File:");
344 		QList<bool> barsNumeric;
345 		barsNumeric << false;
346 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
347 		progressDialog->setOverallTotalSteps(3);
348 		progressDialog->setOverallProgress(0);
349 		progressDialog->setProgress("GI", 0);
350 		progressDialog->show();
351 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
352 		qApp->processEvents();
353 	}
354 	else
355 		progressDialog = nullptr;
356 /* Set default Page to size defined in Preferences */
357 	x = 0.0;
358 	y = 0.0;
359 	b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
360 	h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
361 	if (progressDialog)
362 	{
363 		progressDialog->setOverallProgress(1);
364 		qApp->processEvents();
365 	}
366 	parseHeader(fName, x, y, b, h);
367 	if (b == 0)
368 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
369 	if (h == 0)
370 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
371 	docX = x;
372 	docY = y;
373 	docWidth = b - x;
374 	docHeight = h - y;
375 	baseX = 0;
376 	baseY = 0;
377 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
378 	{
379 		m_Doc->setPage(b-x, h-y, 0, 0, 0, 0, 0, 0, false, false);
380 		m_Doc->addPage(0);
381 		m_Doc->view()->addPage(0, true);
382 		baseX = 0;
383 		baseY = 0;
384 	}
385 	else
386 	{
387 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
388 		{
389 			m_Doc=ScCore->primaryMainWindow()->doFileNew(b-x, h-y, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
390 			ScCore->primaryMainWindow()->HaveNewDoc();
391 			ret = true;
392 			baseX = 0;
393 			baseY = 0;
394 		}
395 	}
396 	if (flags & LoadSavePlugin::lfCreateDoc)
397 	{
398 		m_Doc->documentInfo().setAuthor(docCreator);
399 		m_Doc->documentInfo().setPublisher(docOrganisation);
400 		m_Doc->documentInfo().setTitle(docTitle);
401 		m_Doc->documentInfo().setDate(docDate+" "+docTime);
402 	}
403 	if ((!ret) && (interactive))
404 	{
405 		baseX = m_Doc->currentPage()->xOffset();
406 		baseY = m_Doc->currentPage()->yOffset();
407 	}
408 	if ((ret) || (!interactive))
409 	{
410 		if (b-x > h-y)
411 			m_Doc->setPageOrientation(1);
412 		else
413 			m_Doc->setPageOrientation(0);
414 		m_Doc->setPageSize("Custom");
415 	}
416 	ColorList::Iterator it;
417 	for (it = CustColors.begin(); it != CustColors.end(); ++it)
418 	{
419 		if (!m_Doc->PageColors.contains(it.key()))
420 		{
421 			m_Doc->PageColors.insert(it.key(), it.value());
422 			importedColors.append(it.key());
423 		}
424 	}
425 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
426 		m_Doc->view()->deselectItems();
427 	Elements.clear();
428 	m_Doc->setLoading(true);
429 	m_Doc->DoDrawing = false;
430 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
431 		m_Doc->view()->updatesOn(false);
432 	m_Doc->scMW()->setScriptRunning(true);
433 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
434 	QString CurDirP = QDir::currentPath();
435 	QDir::setCurrent(fi.path());
436 	if (convert(fName))
437 	{
438 		if (Elements.count() == 0)
439 		{
440 			if ((importedColors.count() != 0) && (!((flags & LoadSavePlugin::lfKeepGradients) || (flags & LoadSavePlugin::lfKeepColors) || (flags & LoadSavePlugin::lfKeepPatterns))))
441 			{
442 				for (int cd = 0; cd < importedColors.count(); cd++)
443 				{
444 					m_Doc->PageColors.remove(importedColors[cd]);
445 				}
446 			}
447 			if ((importedGradients.count() != 0) && (!((flags & LoadSavePlugin::lfKeepGradients || (flags & LoadSavePlugin::lfKeepPatterns)))))
448 			{
449 				for (int cd = 0; cd < importedGradients.count(); cd++)
450 				{
451 					m_Doc->docGradients.remove(importedGradients[cd]);
452 				}
453 			}
454 			if ((importedPatterns.count() != 0) && (!(flags & LoadSavePlugin::lfKeepPatterns)))
455 			{
456 				for (int cd = 0; cd < importedPatterns.count(); cd++)
457 				{
458 					m_Doc->docPatterns.remove(importedPatterns[cd]);
459 				}
460 			}
461 		}
462 		tmpSel->clear();
463 		QDir::setCurrent(CurDirP);
464 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
465 			m_Doc->groupObjectsList(Elements);
466 		m_Doc->DoDrawing = true;
467 		m_Doc->scMW()->setScriptRunning(false);
468 		m_Doc->setLoading(false);
469 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
470 		if ((Elements.count() > 0) && (!ret) && (interactive))
471 		{
472 			if (flags & LoadSavePlugin::lfScripted)
473 			{
474 				bool loadF = m_Doc->isLoading();
475 				m_Doc->setLoading(false);
476 				m_Doc->changed();
477 				m_Doc->setLoading(loadF);
478 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
479 				{
480 					m_Doc->m_Selection->delaySignalsOn();
481 					for (int dre=0; dre<Elements.count(); ++dre)
482 					{
483 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
484 					}
485 					m_Doc->m_Selection->delaySignalsOff();
486 					m_Doc->m_Selection->setGroupRect();
487 					if (m_Doc->view() != nullptr)
488 						m_Doc->view()->updatesOn(true);
489 				}
490 			}
491 			else
492 			{
493 				m_Doc->DragP = true;
494 				m_Doc->DraggedElem = nullptr;
495 				m_Doc->DragElements.clear();
496 				m_Doc->m_Selection->delaySignalsOn();
497 				for (int dre=0; dre<Elements.count(); ++dre)
498 				{
499 					tmpSel->addItem(Elements.at(dre), true);
500 				}
501 				tmpSel->setGroupRect();
502 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
503 				m_Doc->itemSelection_DeleteItem(tmpSel);
504 				m_Doc->view()->updatesOn(true);
505 				if ((importedColors.count() != 0) && (!((flags & LoadSavePlugin::lfKeepGradients) || (flags & LoadSavePlugin::lfKeepColors) || (flags & LoadSavePlugin::lfKeepPatterns))))
506 				{
507 					for (int cd = 0; cd < importedColors.count(); cd++)
508 					{
509 						m_Doc->PageColors.remove(importedColors[cd]);
510 					}
511 				}
512 				if ((importedGradients.count() != 0) && (!((flags & LoadSavePlugin::lfKeepGradients || (flags & LoadSavePlugin::lfKeepPatterns)))))
513 				{
514 					for (int cd = 0; cd < importedGradients.count(); cd++)
515 					{
516 						m_Doc->docGradients.remove(importedGradients[cd]);
517 					}
518 				}
519 				if ((importedPatterns.count() != 0) && (!(flags & LoadSavePlugin::lfKeepPatterns)))
520 				{
521 					for (int cd = 0; cd < importedPatterns.count(); cd++)
522 					{
523 						m_Doc->docPatterns.remove(importedPatterns[cd]);
524 					}
525 				}
526 				m_Doc->m_Selection->delaySignalsOff();
527 				// We must copy the TransationSettings object as it is owned
528 				// by handleObjectImport method afterwards
529 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
530 				m_Doc->view()->handleObjectImport(md, transacSettings);
531 				m_Doc->DragP = false;
532 				m_Doc->DraggedElem = nullptr;
533 				m_Doc->DragElements.clear();
534 			}
535 		}
536 		else
537 		{
538 			m_Doc->changed();
539 			m_Doc->reformPages();
540 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
541 				m_Doc->view()->updatesOn(true);
542 		}
543 		success = true;
544 	}
545 	else
546 	{
547 		QDir::setCurrent(CurDirP);
548 		m_Doc->DoDrawing = true;
549 		m_Doc->scMW()->setScriptRunning(false);
550 		m_Doc->view()->updatesOn(true);
551 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
552 	}
553 	if (interactive)
554 		m_Doc->setLoading(false);
555 	//CB If we have a gui we must refresh it if we have used the progressbar
556 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
557 	{
558 		if ((showProgress) && (!interactive))
559 			m_Doc->view()->DrawNew();
560 	}
561 	if (convertedPDF)
562 		QFile::remove(fName);
563 	qApp->restoreOverrideCursor();
564 	return success;
565 }
566 
~AIPlug()567 AIPlug::~AIPlug()
568 {
569 	delete progressDialog;
570 	delete tmpSel;
571 }
572 
extractFromPDF(const QString & infile,const QString & outfile)573 bool AIPlug::extractFromPDF(const QString& infile, const QString& outfile)
574 {
575 	bool ret = false;
576 #ifdef HAVE_PODOFO
577 	QFile outf(outfile);
578 	if (!outf.open(QIODevice::WriteOnly))
579 	{
580 		qDebug()<<"Failed to open QFile outf in AIPlug::extractFromPDF";
581 		return false;
582 	}
583 	try
584 	{
585 		PoDoFo::PdfError::EnableDebug( false );
586 		PoDoFo::PdfError::EnableLogging( false );
587 		PoDoFo::PdfMemDocument doc( infile.toLocal8Bit().data() );
588 		PoDoFo::PdfPage *curPage = doc.GetPage(0);
589 		if (curPage != nullptr)
590 		{
591 			PoDoFo::PdfObject *piece = curPage->GetObject()->GetIndirectKey("PieceInfo");
592 			if (piece != nullptr)
593 			{
594 				PoDoFo::PdfObject *illy = piece->GetIndirectKey("Illustrator");
595 				if (illy != nullptr)
596 				{
597 					PoDoFo::PdfObject *priv = illy->GetIndirectKey("Private");
598 					if (priv == nullptr)
599 						priv = illy;
600 					int num = 0;
601 					PoDoFo::PdfObject *numBl = priv->GetIndirectKey("NumBlock");
602 					if (numBl != nullptr)
603 						num = numBl->GetNumber() + 1;
604 					if (num == 0)
605 						num = 99999;
606 					QString name = "AIPrivateData%1";
607 					QString Key = name.arg(1);
608 					PoDoFo::PdfObject *data = priv->GetIndirectKey(PoDoFo::PdfName(Key.toUtf8().data()));
609 					if (data == nullptr)
610 					{
611 						name = "AIPDFPrivateData%1";
612 						Key = name.arg(1);
613 						data = priv->GetIndirectKey(PoDoFo::PdfName(Key.toUtf8().data()));
614 					}
615 					if (data != nullptr)
616 					{
617 						if (num == 2)
618 						{
619 							Key = name.arg(1);
620 							data = priv->GetIndirectKey(PoDoFo::PdfName(Key.toUtf8().data()));
621 							PoDoFo::PdfStream const *stream = data->GetStream();
622 							PoDoFo::PdfMemoryOutputStream oStream(1);
623 							stream->GetFilteredCopy(&oStream);
624 							oStream.Close();
625 							long bLen = oStream.GetLength();
626 							char *Buffer = oStream.TakeBuffer();
627 							outf.write(Buffer, bLen);
628 							free( Buffer );
629 						}
630 						else
631 						{
632 							for (int a = 2; a < num; a++)
633 							{
634 								Key = name.arg(a);
635 								data = priv->GetIndirectKey(PoDoFo::PdfName(Key.toUtf8().data()));
636 								if (data == nullptr)
637 									break;
638 								PoDoFo::PdfStream const *stream = data->GetStream();
639 								PoDoFo::PdfMemoryOutputStream oStream(1);
640 								stream->GetFilteredCopy(&oStream);
641 								oStream.Close();
642 								long bLen = oStream.GetLength();
643 								char *Buffer = oStream.TakeBuffer();
644 								outf.write(Buffer, bLen);
645 								free( Buffer );
646 							}
647 						}
648 					}
649 					ret = true;
650 				}
651 			}
652 		}
653 		outf.close();
654 	}
655 	catch (PoDoFo::PdfError& e)
656 	{
657 		outf.close();
658 		qDebug("Scribus caught and handled the following exception from PoDoFo while processing a PDF format ai file:\n----\n");
659 		e.PrintErrorMsg();
660 		qDebug("----\nThe ai file could not be imported.\n");
661 		QFile::remove(outfile);
662 		return false;
663 	}
664 #endif
665 	return ret;
666 }
667 
decompressAIData(QString & fName)668 bool AIPlug::decompressAIData(QString &fName)
669 {
670 	QString f2 = fName+"_decom.ai";
671 	char buffer[4096];
672 
673 	QFile source(fName);
674 	if (!source.open(QFile::ReadOnly))
675 		return false;
676 	if (!source.seek(20))
677 	{
678 		source.close();
679 		return false;
680 	}
681 
682 	QtIOCompressor compressor(&source);
683 	compressor.setStreamFormat(QtIOCompressor::ZlibFormat);
684 	if (!compressor.open(QIODevice::ReadOnly))
685 	{
686 		source.close();
687 		return false;
688 	}
689 
690 	QFile dest(f2);
691 	if (!dest.open(QFile::WriteOnly))
692 	{
693 		source.close();
694 		return false;
695 	}
696 	QDataStream destStream(&dest);
697 
698 	qint64 bytesRead = -1;
699 	qint64 bytesWritten = -1;
700 
701 	bytesRead = compressor.read(buffer, 4096);
702 	while (bytesRead > 0)
703 	{
704 		bytesWritten = destStream.writeRawData(buffer, (int) bytesRead);
705 		if (bytesWritten < 0)
706 			break;
707 		bytesRead = compressor.read(buffer, 4096);
708 	}
709 
710 	compressor.close();
711 	source.close();
712 	dest.close();
713 
714 	if (bytesRead < 0 || bytesWritten < 0)
715 		return false;
716 
717 	if (!convertedPDF)
718 	{
719 		QFileInfo bF2(fName);
720 		QString tmpFile = ScPaths::tempFileDir()+ "/"+bF2.baseName()+"_tmp.ai";
721 		moveFile(f2, tmpFile);
722 		fName = tmpFile;
723 		convertedPDF = true;
724 	}
725 	else
726 	{
727 		QFile::remove(fName);
728 		fName = f2;
729 	}
730 	return true;
731 }
732 
parseHeader(const QString & fName,double & x,double & y,double & b,double & h)733 bool AIPlug::parseHeader(const QString& fName, double &x, double &y, double &b, double &h)
734 {
735 	QString tmp, BBox, FarNam;
736 	ScColor cc;
737 	double c, m, yc, k;
738 	bool found = false;
739 	QFile f(fName);
740 	if (f.open(QIODevice::ReadOnly))
741 	{
742 /* Try to find Bounding Box */
743 		bool isAtend = false;
744 		QDataStream ts(&f);
745 		while (!ts.atEnd())
746 		{
747 			tmp = readLineFromDataStream(ts);
748 			if (tmp.startsWith("%%BoundingBox:"))
749 			{
750 				found = true;
751 				BBox = tmp.remove("%%BoundingBox:");
752 			}
753 			if (!found)
754 			{
755 				if (tmp.startsWith("%%BoundingBox"))
756 				{
757 					found = true;
758 					BBox = tmp.remove("%%BoundingBox");
759 				}
760 			}
761 			if (tmp.startsWith("%%HiResBoundingBox:"))
762 			{
763 				found = true;
764 				BBox = tmp.remove("%%HiResBoundingBox:");
765 			}
766 		//	if (tmp.startsWith("%AI3_TileBox:"))
767 		//	{
768 		//		found = true;
769 		//		BBox = tmp.remove("%AI3_TileBox:");
770 		//	}
771 			if (tmp.startsWith("%%For"))
772 			{
773 				QStringList res = getStrings(tmp);
774 				if (res.count() > 1)
775 				{
776 					docCreator = res[0];
777 					docOrganisation = res[1];
778 				}
779 			}
780 			if (tmp.startsWith("%%CreationDate:"))
781 			{
782 				QStringList res = getStrings(tmp);
783 				if (res.count() > 1)
784 				{
785 					docDate = res[0];
786 					docTime = res[1];
787 				}
788 				else
789 				{
790 					docDate = tmp.remove("%%CreationDate: ");
791 					docTime = "";
792 				}
793 			}
794 			if (tmp.startsWith("%%Title"))
795 			{
796 				QStringList res = getStrings(tmp);
797 				if (res.count() > 0)
798 					docTitle = res[0];
799 			}
800 			if ((tmp.startsWith("%%CMYKCustomColor")) || (tmp.startsWith("%%CMYKProcessColor")))
801 			{
802 				if (tmp.contains("(atend)"))
803 					isAtend = true;
804 				else
805 				{
806 					if (tmp.startsWith("%%CMYKCustomColor"))
807 						tmp = tmp.remove(0,18);
808 					else if (tmp.startsWith("%%CMYKProcessColor"))
809 						tmp = tmp.remove(0,19);
810 					ScTextStream ts2(&tmp, QIODevice::ReadOnly);
811 					ts2 >> c >> m >> yc >> k;
812 					FarNam = ts2.readAll();
813 					FarNam = FarNam.trimmed();
814 					FarNam = FarNam.remove(0,1);
815 					FarNam = FarNam.remove(FarNam.length()-1,1);
816 					FarNam = FarNam.simplified();
817 					QByteArray farN;
818 					for (int a = 0; a < FarNam.length(); a++)
819 					{
820 						QChar ch = FarNam.at(a);
821 						uint chc = ch.unicode();
822 						if (chc > 255)
823 							farN.append(chc >> 8);
824 						farN.append(chc & 0x00FF);
825 					}
826 					FarNam = QString::fromUtf8(farN.constData());
827 					cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * yc), qRound(255 * k));
828 					cc.setSpotColor(true);
829 					if (!FarNam.isEmpty())
830 						CustColors.tryAddColor(FarNam, cc);
831 					while (!ts.atEnd())
832 					{
833 						quint64 oldPos = ts.device()->pos();
834 						tmp = readLineFromDataStream(ts);
835 						if (!tmp.startsWith("%%+"))
836 						{
837 							ts.device()->seek(oldPos);
838 							break;
839 						}
840 						tmp = tmp.remove(0,3);
841 						ScTextStream ts2(&tmp, QIODevice::ReadOnly);
842 						ts2 >> c >> m >> yc >> k;
843 						FarNam = ts2.readAll();
844 						FarNam = FarNam.trimmed();
845 						FarNam = FarNam.remove(0,1);
846 						FarNam = FarNam.remove(FarNam.length()-1,1);
847 						FarNam = FarNam.simplified();
848 						QByteArray farN;
849 						for (int a = 0; a < FarNam.length(); a++)
850 						{
851 							QChar ch = FarNam.at(a);
852 							uint chc = ch.unicode();
853 							if (chc > 255)
854 								farN.append(chc >> 8);
855 							farN.append(chc & 0x00FF);
856 						}
857 						FarNam = QString::fromUtf8(farN.constData());
858 						cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * yc), qRound(255 * k));
859 						cc.setSpotColor(true);
860 						if (!FarNam.isEmpty())
861 							CustColors.tryAddColor(FarNam, cc);
862 					}
863 				}
864 			}
865 			if ((tmp.startsWith("%%RGBCustomColor")) || (tmp.startsWith("%%RGBProcessColor")))
866 			{
867 				if (tmp.contains("(atend)"))
868 					isAtend = true;
869 				else
870 				{
871 					if (tmp.startsWith("%%RGBCustomColor"))
872 						tmp = tmp.remove(0,17);
873 					else if (tmp.startsWith("%%RGBProcessColor"))
874 						tmp = tmp.remove(0,18);
875 					ScTextStream ts2(&tmp, QIODevice::ReadOnly);
876 					ts2 >> c >> m >> yc;
877 					FarNam = ts2.readAll();
878 					FarNam = FarNam.trimmed();
879 					FarNam = FarNam.remove(0,1);
880 					FarNam = FarNam.remove(FarNam.length()-1,1);
881 					FarNam = FarNam.simplified();
882 					QByteArray farN;
883 					for (int a = 0; a < FarNam.length(); a++)
884 					{
885 						QChar ch = FarNam.at(a);
886 						uint chc = ch.unicode();
887 						if (chc > 255)
888 							farN.append(chc >> 8);
889 						farN.append(chc & 0x00FF);
890 					}
891 					FarNam = QString::fromUtf8(farN.constData());
892 					cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * yc));
893 					if (!FarNam.isEmpty())
894 						CustColors.tryAddColor(FarNam, cc);
895 					while (!ts.atEnd())
896 					{
897 						quint64 oldPos = ts.device()->pos();
898 						tmp = readLineFromDataStream(ts);
899 						if (!tmp.startsWith("%%+"))
900 						{
901 							ts.device()->seek(oldPos);
902 							break;
903 						}
904 						tmp = tmp.remove(0,3);
905 						ScTextStream ts2(&tmp, QIODevice::ReadOnly);
906 						ts2 >> c >> m >> yc;
907 						FarNam = ts2.readAll();
908 						FarNam = FarNam.trimmed();
909 						FarNam = FarNam.remove(0,1);
910 						FarNam = FarNam.remove(FarNam.length()-1,1);
911 						FarNam = FarNam.simplified();
912 						QByteArray farN;
913 						for (int a = 0; a < FarNam.length(); a++)
914 						{
915 							QChar ch = FarNam.at(a);
916 							uint chc = ch.unicode();
917 							if (chc > 255)
918 								farN.append(chc >> 8);
919 							farN.append(chc & 0x00FF);
920 						}
921 						FarNam = QString::fromUtf8(farN.constData());
922 						cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * yc));
923 						if (!FarNam.isEmpty())
924 							CustColors.tryAddColor(FarNam, cc);
925 					}
926 				}
927 			}
928 			if (tmp.startsWith("%%EndComments"))
929 			{
930 				while (!ts.atEnd())
931 				{
932 					bool isX = false;
933 					tmp = readLineFromDataStream(ts);
934 					if ((tmp.endsWith("Xa") || tmp.endsWith(" k") || tmp.endsWith(" x")) && (tmp.length() > 4))
935 					{
936 						ScTextStream ts2(&tmp, QIODevice::ReadOnly);
937 						ts2 >> c >> m >> yc >> k;
938 						if (tmp.endsWith(" x"))
939 						{
940 							isX = true;
941 							int an = tmp.indexOf("(");
942 							int en = tmp.lastIndexOf(")");
943 							FarNam = tmp.mid(an+1, en-an-1);
944 							FarNam = FarNam.simplified();
945 							QByteArray farN;
946 							for (int a = 0; a < FarNam.length(); a++)
947 							{
948 								QChar ch = FarNam.at(a);
949 								uint chc = ch.unicode();
950 								if (chc > 255)
951 									farN.append(chc >> 8);
952 								farN.append(chc & 0x00FF);
953 							}
954 							FarNam = QString::fromUtf8(farN.constData());
955 						}
956 						tmp = readLineFromDataStream(ts);
957 						if (tmp.endsWith("Pc"))
958 						{
959 							if (!isX)
960 							{
961 								tmp = tmp.trimmed();
962 								tmp = tmp.remove(0,1);
963 								int en = tmp.indexOf(")");
964 								FarNam = tmp.mid(0, en);
965 								FarNam = FarNam.simplified();
966 								QByteArray farN;
967 								for (int a = 0; a < FarNam.length(); a++)
968 								{
969 									QChar ch = FarNam.at(a);
970 									uint chc = ch.unicode();
971 									if (chc > 255)
972 										farN.append(chc >> 8);
973 									farN.append(chc & 0x00FF);
974 								}
975 								FarNam = QString::fromUtf8(farN.constData());
976 							}
977 							cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * yc), qRound(255 * k));
978 							cc.setSpotColor(true);
979 							CustColors.tryAddColor(FarNam, cc);
980 						}
981 					}
982 				}
983 				if (!isAtend)
984 					break;
985 			}
986 		}
987 		f.close();
988 		if (found)
989 		{
990 			QStringList bb = BBox.split(" ", Qt::SkipEmptyParts);
991 			if (bb.count() == 4)
992 			{
993 				x = ScCLocale::toDoubleC(bb[0]);
994 				y = ScCLocale::toDoubleC(bb[1]);
995 				b = ScCLocale::toDoubleC(bb[2]);
996 				h = ScCLocale::toDoubleC(bb[3]);
997 			}
998 		}
999 	}
1000 	return found;
1001 }
1002 
removeAIPrefix(QString comment)1003 QString AIPlug::removeAIPrefix(QString comment)
1004 {
1005 	QString tmp;
1006 	if (comment.startsWith("%AI"))
1007 	{
1008 		int an = comment.indexOf("_");
1009 		tmp = comment.remove(0, an+1);
1010 	}
1011 	else
1012 		tmp = comment;
1013 	return tmp;
1014 }
1015 
parseColor(QString data)1016 QString AIPlug::parseColor(QString data)
1017 {
1018 	QString ret = CommonStrings::None;
1019 	if (data.isEmpty())
1020 		return ret;
1021 	double c, m, y, k;
1022 	ScColor tmp;
1023 	ScTextStream Code(&data, QIODevice::ReadOnly);
1024 	Code >> c;
1025 	Code >> m;
1026 	Code >> y;
1027 	Code >> k;
1028 	tmp.setColorF(c, m, y, k);
1029 	tmp.setSpotColor(false);
1030 	tmp.setRegistrationColor(false);
1031 	QString namPrefix = "FromAI";
1032 	QString fNam = m_Doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
1033 	if (fNam == namPrefix+tmp.name())
1034 		importedColors.append(fNam);
1035 	ret = fNam;
1036 	meshColorMode = 0;
1037 	return ret;
1038 }
1039 
parseColorGray(QString data)1040 QString AIPlug::parseColorGray(QString data)
1041 {
1042 	QString ret = CommonStrings::None;
1043 	if (data.isEmpty())
1044 		return ret;
1045 	double k;
1046 	ScColor tmp;
1047 	ColorList::Iterator it;
1048 	ScTextStream Code(&data, QIODevice::ReadOnly);
1049 	Code >> k;
1050 	tmp.setColorF(0, 0, 0, 1.0 - k);
1051 	tmp.setSpotColor(false);
1052 	tmp.setRegistrationColor(false);
1053 	QString namPrefix = "FromAI";
1054 	QString fNam = m_Doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
1055 	if (fNam == namPrefix+tmp.name())
1056 		importedColors.append(fNam);
1057 	ret = fNam;
1058 	meshColorMode = 2;
1059 	return ret;
1060 }
1061 
parseColorRGB(QString data)1062 QString AIPlug::parseColorRGB(QString data)
1063 {
1064 	QString ret = CommonStrings::None;
1065 	if (data.isEmpty())
1066 		return ret;
1067 	double r, g, b;
1068 	ScColor tmp;
1069 	ScTextStream Code(&data, QIODevice::ReadOnly);
1070 	Code >> r;
1071 	Code >> g;
1072 	Code >> b;
1073 	tmp.setRgbColorF(r, g, b);
1074 	tmp.setSpotColor(false);
1075 	tmp.setRegistrationColor(false);
1076 	QString namPrefix = "FromAI";
1077 	QString fNam = m_Doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
1078 	if (fNam == namPrefix+tmp.name())
1079 		importedColors.append(fNam);
1080 	ret = fNam;
1081 	meshColorMode = 1;
1082 	return ret;
1083 }
1084 
parseCustomColor(QString data,double & shade)1085 QString AIPlug::parseCustomColor(QString data, double &shade)
1086 {
1087 	QString ret = CommonStrings::None;
1088 	if (data.isEmpty())
1089 		return ret;
1090 	double c, m, y, k, sh;
1091 	ScColor tmp;
1092 	ScTextStream Code(&data, QIODevice::ReadOnly);
1093 	Code >> c;
1094 	Code >> m;
1095 	Code >> y;
1096 	Code >> k;
1097 	int an = data.indexOf("(");
1098 	int en = data.lastIndexOf(")");
1099 	QString FarNam = data.mid(an+1, en-an-1);
1100 	FarNam.remove("\\");
1101 	QString FarSha = data.mid(en+1, data.size() - en);
1102 	ScTextStream Val(&FarSha, QIODevice::ReadOnly);
1103 	Val >> sh;
1104 	shade = (1.0 - sh) * 100.0;
1105 	tmp.setColorF(c, m, y, k);
1106 	tmp.setSpotColor(true);
1107 	tmp.setRegistrationColor(false);
1108 	QString fNam = m_Doc->PageColors.tryAddColor(FarNam, tmp);
1109 	if (fNam == FarNam)
1110 		importedColors.append(FarNam);
1111 	ret = fNam;
1112 	meshColorMode = 0;
1113 	return ret;
1114 }
1115 
parseCustomColorX(QString data,double & shade,const QString & type)1116 QString AIPlug::parseCustomColorX(QString data, double &shade, const QString& type)
1117 {
1118 	QString ret = CommonStrings::None;
1119 	if (data.isEmpty())
1120 		return ret;
1121 	double c, m, y, k, sh, r, g, b;
1122 	ScColor tmp;
1123 	ScTextStream Code(&data, QIODevice::ReadOnly);
1124 	if (type == "1")
1125 	{
1126 		Code >> r;
1127 		Code >> g;
1128 		Code >> b;
1129 		tmp.setRgbColorF(r, g, b);
1130 		meshColorMode = 1;
1131 	}
1132 	else
1133 	{
1134 		Code >> c;
1135 		Code >> m;
1136 		Code >> y;
1137 		Code >> k;
1138 		tmp.setColorF(c, m, y, k);
1139 		meshColorMode = 0;
1140 	}
1141 	int an = data.indexOf("(");
1142 	int en = data.lastIndexOf(")");
1143 	QString FarNam = data.mid(an+1, en-an-1);
1144 	FarNam.remove("\\");
1145 	QString FarSha = data.mid(en+1, data.size() - en);
1146 	ScTextStream Val(&FarSha, QIODevice::ReadOnly);
1147 	Val >> sh;
1148 	shade = (1.0 - sh) * 100.0;
1149 	if (type == "0")
1150 		tmp.setSpotColor(true);
1151 	tmp.setRegistrationColor(false);
1152 	QString fNam = m_Doc->PageColors.tryAddColor(FarNam, tmp);
1153 	if (fNam == FarNam)
1154 		importedColors.append(FarNam);
1155 	ret = fNam;
1156 	return ret;
1157 }
1158 
getStrings(const QString & data)1159 QStringList AIPlug::getStrings(const QString& data)
1160 {
1161 	QStringList result;
1162 	result.clear();
1163 	QChar tmp;
1164 	QString tmp2;
1165 	QString tmp3;
1166 	bool paran = false;
1167 	bool skip = false;
1168 	int digitCount = 0;
1169 	for (int i = 0; i < data.count(); i++)
1170 	{
1171 		tmp = data[i];
1172 		if (skip)
1173 		{
1174 			if (paran)
1175 			{
1176 				if (tmp.isDigit())
1177 				{
1178 					tmp3 += tmp;
1179 					digitCount++;
1180 					if (digitCount == 3)
1181 					{
1182 						bool ok = false;
1183 						int code = tmp3.toInt(&ok, 8);
1184 						if (ok)
1185 							tmp2 += QChar(code);
1186 						digitCount = 0;
1187 						tmp3 = "";
1188 						skip = false;
1189 					}
1190 				}
1191 				else
1192 				{
1193 					if (tmp == 'r')
1194 						tmp = SpecialChars::PARSEP;
1195 					tmp2 += tmp;
1196 					skip = false;
1197 				}
1198 			}
1199 			continue;
1200 		}
1201 		if (tmp == '(')
1202 		{
1203 			paran = true;
1204 			continue;
1205 		}
1206 		if (tmp == ')')
1207 		{
1208 			paran = false;
1209 			result.append(tmp2);
1210 			tmp2 = "";
1211 			continue;
1212 		}
1213 		if (tmp == '\\')
1214 		{
1215 			skip = true;
1216 			continue;
1217 		}
1218 		if (paran)
1219 			tmp2 += tmp;
1220 	}
1221 	return result;
1222 }
1223 
getCommands(const QString & data,QStringList & commands)1224 void AIPlug::getCommands(const QString& data, QStringList &commands)
1225 {
1226 	QString tmp;
1227 	QString tmp2;
1228 	QString tmp3;
1229 	bool paran = false;
1230 	//bool arra = false;
1231 	bool skip = false;
1232 	for (int a = 0; a < data.count(); a++)
1233 	{
1234 		tmp = data[a];
1235 		if (skip)
1236 		{
1237 			tmp2 += tmp;
1238 			skip = false;
1239 			continue;
1240 		}
1241 		if (tmp == "(")
1242 		{
1243 			paran = true;
1244 			tmp2 += tmp;
1245 			continue;
1246 		}
1247 		if (tmp == ")")
1248 		{
1249 			paran = false;
1250 			tmp2 += tmp;
1251 			continue;
1252 		}
1253 		if (tmp == "[")
1254 		{
1255 		//	arra = true;
1256 			tmp2 += tmp;
1257 			continue;
1258 		}
1259 		if (tmp == "]")
1260 		{
1261 		//	arra = false;
1262 			tmp2 += tmp;
1263 			continue;
1264 		}
1265 //		if (tmp == "\\")
1266 //		{
1267 //			skip = true;
1268 //			continue;
1269 //		}
1270 		if (!paran)
1271 		{
1272 			if (tmp == " ")
1273 			{
1274 				tmp3 += " " + tmp2;
1275 				if (commandList.contains(tmp2))
1276 				{
1277 					commands.append(tmp3);
1278 					tmp3 = "";
1279 				}
1280 				tmp2 = "";
1281 				continue;
1282 			}
1283 		}
1284 		tmp2 += tmp;
1285 	}
1286 	if (!tmp2.isEmpty())
1287 	{
1288 		tmp3 += " " + tmp2;
1289 		commands.append(tmp3);
1290 	}
1291 }
1292 
decodeA85(QByteArray & psdata,const QString & tmp)1293 void AIPlug::decodeA85(QByteArray &psdata, const QString& tmp)
1294 {
1295 	uchar byte;
1296 	ushort data;
1297 	unsigned long sum = 0;
1298 	int quintet = 0;
1299 	for (int c = 0; c < tmp.length(); c++)
1300 	{
1301 		byte = QChar(tmp.at(c)).cell();
1302 		if (byte >= '!' && byte <= 'u')
1303 		{
1304 			sum = sum * 85 + ((unsigned long)byte - '!');
1305 			quintet++;
1306 			if (quintet == 5)
1307 			{
1308 				psdata.resize(psdata.size()+4);
1309 				data = (sum >> 24) & 0xFF;
1310 				psdata[psdata.size()-4] = data;
1311 				data = (sum >> 16) & 0xFF;
1312 				psdata[psdata.size()-3] = data;
1313 				data = (sum >> 8) & 0xFF;
1314 				psdata[psdata.size()-2] = data;
1315 				data = sum & 0xFF;
1316 				psdata[psdata.size()-1] = data;
1317 				quintet = 0;
1318 				sum = 0;
1319 			}
1320 		}
1321 		else if (byte == 'z')
1322 		{
1323 			psdata.resize(psdata.size()+4);
1324 			psdata[psdata.size()-4] = 0;
1325 			psdata[psdata.size()-3] = 0;
1326 			psdata[psdata.size()-2] = 0;
1327 			psdata[psdata.size()-1] = 0;
1328 		}
1329 		else if (byte == '~')
1330 		{
1331 			if (quintet)
1332 			{
1333 				int i;
1334 				for (i = 0; i < 5 - quintet; i++)
1335 					sum *= 85;
1336 				if (quintet > 1)
1337 					sum += (0xFFFFFF >> ((quintet - 2) * 8));
1338 				for (i = 0; i < quintet - 1; i++)
1339 				{
1340 					data = (sum >> (24 - 8 * i)) & 0xFF;
1341 					psdata.resize(psdata.size()+1);
1342 					psdata[psdata.size()-1] = data;
1343 				}
1344 				quintet = 0;
1345 			}
1346 			break;
1347 		}
1348 	}
1349 }
1350 
processData(const QString & data)1351 void AIPlug::processData(const QString& data)
1352 {
1353 	double x, y, x1, y1, x2, y2;
1354 	int z, tmpInt;
1355 	PageItem *ite;
1356 	QString command = "";
1357 	QString Cdata = "";
1358 	QStringList da;
1359 	if (dataMode && fObjectMode)
1360 	{
1361 		if (data.contains("~>"))
1362 		{
1363 			dataString += data.midRef(1);
1364 			dataMode = false;
1365 			QByteArray fData;
1366 			decodeA85(fData, dataString);
1367 			dataString = "";
1368 			if (fObjectMode)
1369 			{
1370 				FPoint wh = currentSpecialPath.widthHeight();
1371 				if ((currentSpecialPath.size() > 3) && (wh.x() != 0.0) && (wh.y() != 0.0))
1372 				{
1373 					z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX, baseY, 10, 10, 0, CommonStrings::None, CommonStrings::None);
1374 					ite = m_Doc->Items->at(z);
1375 					ite->PoLine = currentSpecialPath.copy();
1376 					ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1377 					ite->ClipEdited = true;
1378 					ite->FrameType = 3;
1379 					ite->setFillShade(CurrFillShade);
1380 					ite->setLineShade(CurrStrokeShade);
1381 					ite->setFillEvenOdd(fillRule);
1382 					ite->setFillTransparency(1.0 - Opacity);
1383 					ite->setLineTransparency(1.0 - Opacity);
1384 					ite->setFillBlendmode(blendMode);
1385 					ite->setLineBlendmode(blendMode);
1386 					ite->setLineEnd(CapStyle);
1387 					ite->setLineJoin(JoinStyle);
1388 					wh = getMaxClipF(&ite->PoLine);
1389 					ite->setWidthHeight(wh.x(),wh.y());
1390 					ite->setTextFlowMode(PageItem::TextFlowDisabled);
1391 					m_Doc->adjustItemSize(ite);
1392 					QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_ai_XXXXXX.pdf");
1393 					tempFile->setAutoRemove(false);
1394 					tempFile->open();
1395 					tempFile->write(fData);
1396 					QString imgName = getLongPathName(tempFile->fileName());
1397 					tempFile->close();
1398 					ite->isInlineImage = true;
1399 					ite->isTempFile = true;
1400 					m_Doc->loadPict(imgName, ite);
1401 					delete tempFile;
1402 					if (ite->imageIsAvailable)
1403 						ite->setImageXYScale(ite->width() / ite->pixm.width(), ite->height() / ite->pixm.height());
1404 					ite->setImageFlippedV(true);
1405 					ite->Clip = flattenPath(ite->PoLine, ite->Segments);
1406 					ite->setRedrawBounding();
1407 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
1408 						ite->setLocked(itemLocked);
1409 					if (patternMode)
1410 						PatternElements.append(ite);
1411 					else
1412 						Elements.append(ite);
1413 					if (groupStack.count() != 0)
1414 						groupStack.top().append(ite);
1415 				}
1416 			}
1417 			fObjectMode = false;
1418 			currentSpecialPath.resize(0);
1419 			currentSpecialPath.svgInit();
1420 		}
1421 		else
1422 		{
1423 			dataString += data.midRef(1);
1424 		}
1425 		return;
1426 	}
1427 	getCommands(data, da);
1428 	for (int a = 0; a < da.count(); a++)
1429 	{
1430 		Cdata = da[a];
1431 		if (((Cdata.startsWith("%")) || (Cdata.startsWith(" %"))) && (!meshMode))
1432 			continue;
1433 		if (Cdata.contains("SymbolInstance"))
1434 		{
1435 			symbolMode = true;
1436 			return;
1437 		}
1438 		if (symbolMode)
1439 		{
1440 			if (Cdata.contains("SymbolRef"))
1441 			{
1442 				int an = Cdata.indexOf("(");
1443 				int en = Cdata.lastIndexOf(")");
1444 				if ((an != -1) && (en != -1))
1445 				{
1446 					currentSymbolName = Cdata.mid(an+1, en-an-1);
1447 					currentSymbolName.remove("\\");
1448 					currentSymbolName = "S_"+currentSymbolName.trimmed().simplified().replace(" ", "_");
1449 				}
1450 			}
1451 			else if (Cdata.contains("TransformMatrix"))
1452 			{
1453 				ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1454 				ts2 >> x >> y >> x1 >> y1 >> x2 >> y2;
1455 				QTransform symTrans = QTransform(x, y, x1, y1, x2, y2);
1456 				double rotation = getRotationFromMatrix(symTrans, 0.0);
1457 				QTransform symT;
1458 				symT.translate(x2, y2);
1459 				QPointF pos1 = importedSymbols[currentSymbolName];
1460 				pos1 = symT.map(pos1);
1461 				double xp = pos1.x();
1462 				double yp = pos1.y();
1463 			//	xp += m_Doc->currentPage()->xOffset();
1464 			//	yp += m_Doc->currentPage()->yOffset();
1465 				int z = m_Doc->itemAdd(PageItem::Symbol, PageItem::Unspecified, baseX + xp, baseY + yp, 1, 1, 0, CommonStrings::None, CommonStrings::None);
1466 				PageItem *b = m_Doc->Items->at(z);
1467 				b->m_layerID = m_Doc->activeLayer();
1468 				ScPattern pat = m_Doc->docPatterns[currentSymbolName];
1469 				b->setWidth(pat.width * symTrans.m11());
1470 				b->setHeight(pat.height * symTrans.m22());
1471 				b->OldB2 = b->width();
1472 				b->OldH2 = b->height();
1473 				b->setPattern(currentSymbolName);
1474 				double xoffset = 0.0, yoffset = 0.0;
1475 			//	if (rotation != 0.0)
1476 			//	{
1477 			//		double temp = -b->height();
1478 			//		xoffset = sin(-rotation) * temp;
1479 			//		yoffset = cos(-rotation) * temp;
1480 			//	}
1481 				b->setXPos(xp + xoffset);
1482 				b->setYPos(yp + yoffset);
1483 				m_Doc->setRotationMode(3);
1484 				m_Doc->rotateItem(rotation * 180 / M_PI, b);
1485 				m_Doc->setRotationMode(0);
1486 //				b->setRotation(rotation * 180 / M_PI);
1487 				b->setTextFlowMode(PageItem::TextFlowDisabled);
1488 				b->setFillTransparency(1.0 - Opacity);
1489 				b->setLineTransparency(1.0 - Opacity);
1490 				b->setFillBlendmode(blendMode);
1491 				b->setLineBlendmode(blendMode);
1492 				b->updateClip();
1493 				if (patternMode)
1494 					PatternElements.append(b);
1495 				else
1496 					Elements.append(b);
1497 				if (groupStack.count() != 0)
1498 					groupStack.top().append(b);
1499 				symbolMode = false;
1500 			}
1501 		}
1502 		QStringList da2 = Cdata.split(" ", Qt::SkipEmptyParts);
1503 		if (da2.count() == 0)
1504 			return;
1505 		command = da2.last();
1506 /* Start Path construction commands */
1507 		if (command == "m")
1508 		{
1509 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1510 			ts2 >> x >> y;
1511 			Coords.svgMoveTo(x - docX, docHeight - (y - docY));
1512 			currentPoint = FPoint(x - docX, docHeight - (y - docY));
1513 		}
1514 		else if ((command == "L") || (command == "l"))
1515 		{
1516 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1517 			ts2 >> x >> y;
1518 			Coords.svgLineTo(x - docX, docHeight - (y - docY));
1519 			currentPoint = FPoint(x - docX, docHeight - (y - docY));
1520 		}
1521 		else if ((command == "C") || (command == "c"))
1522 		{
1523 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1524 			ts2 >> x >> y >> x1 >> y1 >> x2 >> y2;
1525 			Coords.svgCurveToCubic(x - docX, docHeight - (y - docY),
1526 								   x1 - docX, docHeight - (y1 - docY),
1527 								   x2 - docX, docHeight - (y2 - docY));
1528 			currentPoint = FPoint(x2 - docX, docHeight - (y2 - docY));
1529 		}
1530 		else if ((command == "Y") || (command == "y"))
1531 		{
1532 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1533 			ts2 >> x1 >> y1 >> x2 >> y2;
1534 			Coords.svgCurveToCubic(x1 - docX, docHeight - (y1 - docY), x2 - docX, docHeight - (y2 - docY), x2 - docX, docHeight - (y2 - docY));
1535 			currentPoint = FPoint(x2 - docX, docHeight - (y2 - docY));
1536 		}
1537 		else if ((command == "V") || (command == "v"))
1538 		{
1539 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1540 			ts2 >> x >> y >> x2 >> y2;
1541 			Coords.svgCurveToCubic(currentPoint.x(), currentPoint.y(), x - docX, docHeight - (y - docY), x2 - docX, docHeight - (y2 - docY));
1542 			currentPoint = FPoint(x2 - docX, docHeight - (y2 - docY));
1543 		}
1544 /* End Path construction commands */
1545 /* Start Object creation commands */
1546 		else if ((command == "b") || (command == "B") || (command == "f") || (command == "F") || (command == "s") || (command == "S"))
1547 		{
1548 			FPoint wh = Coords.widthHeight();
1549 			if ((Coords.size() > 3) && (wh.x() != 0.0) && (wh.y() != 0.0))
1550 			{
1551 				if ((!WasU) || ((WasU) && (FirstU)))
1552 				{
1553 					if ((command == "B") || (command == "F") || (command == "S"))
1554 					{
1555 						if (command == "F")
1556 							z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CommonStrings::None);
1557 						else if (command == "B")
1558 							z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
1559 						else
1560 							z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CommonStrings::None, CurrColorStroke);
1561 					}
1562 					else
1563 					{
1564 						if (command == "f")
1565 							z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CommonStrings::None);
1566 						else if (command == "b")
1567 							z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
1568 						else
1569 							z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CommonStrings::None, CurrColorStroke);
1570 					}
1571 					ite = m_Doc->Items->at(z);
1572 					ite->PoLine = Coords.copy();
1573 					ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1574 					ite->ClipEdited = true;
1575 					ite->FrameType = 3;
1576 					ite->setFillShade(CurrFillShade);
1577 					ite->setLineShade(CurrStrokeShade);
1578 					ite->setFillEvenOdd(fillRule);
1579 					ite->setFillTransparency(1.0 - Opacity);
1580 					ite->setLineTransparency(1.0 - Opacity);
1581 					ite->setFillBlendmode(blendMode);
1582 					ite->setLineBlendmode(blendMode);
1583 					if (!currentPatternName.isEmpty())
1584 					{
1585 						ite->setPattern(currentPatternName);
1586 						ite->setPatternTransform(currentPatternXScale * 100, currentPatternYScale * 100, currentPatternX, currentPatternY, currentPatternRotation, 0.0, 0.0);
1587 						ite->GrType = Gradient_Pattern;
1588 						currentPatternName.clear();
1589 					}
1590 					if (!currentStrokePatternName.isEmpty())
1591 					{
1592 						ite->setStrokePattern(currentStrokePatternName);
1593 						ite->setStrokePatternTransform(currentStrokePatternXScale * 100, currentStrokePatternYScale * 100, currentStrokePatternX, currentStrokePatternY, currentStrokePatternRotation, 0.0, 0.0, 1.0);
1594 						currentStrokePatternName.clear();
1595 					}
1596 					ite->setLineEnd(CapStyle);
1597 					ite->setLineJoin(JoinStyle);
1598 					if (!WasU)
1599 					{
1600 						FPoint wh = getMaxClipF(&ite->PoLine);
1601 						ite->setWidthHeight(wh.x(),wh.y());
1602 						ite->setTextFlowMode(PageItem::TextFlowDisabled);
1603 						m_Doc->adjustItemSize(ite);
1604 					}
1605 					if (patternMode)
1606 						PatternElements.append(ite);
1607 					else
1608 						Elements.append(ite);
1609 					if (groupStack.count() != 0)
1610 						groupStack.top().append(ite);
1611 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
1612 						ite->setLocked(itemLocked);
1613 
1614 				}
1615 				else if (m_Doc->Items->count() > 0)
1616 				{
1617 					ite = m_Doc->Items->last();
1618 					ite->PoLine.setMarker();
1619 					Coords.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1620 					ite->PoLine.putPoints(ite->PoLine.size(), Coords.size(), Coords);
1621 				}
1622 				FirstU = false;
1623 				itemRendered = true;
1624 				CurrFillShade = 100.0;
1625 				CurrStrokeShade = 100.0;
1626 			}
1627 			Coords.resize(0);
1628 			Coords.svgInit();
1629 		}
1630 		else if (command == "*u")
1631 		{
1632 			FirstU = true;
1633 			WasU = true;
1634 		}
1635 		else if (command == "*U")
1636 		{
1637 			if (m_Doc->Items->count() > 0)
1638 			{
1639 				WasU = false;
1640 				ite = m_Doc->Items->last();
1641 				FPoint wh = getMaxClipF(&ite->PoLine);
1642 				ite->setWidthHeight(wh.x(),wh.y());
1643 				m_Doc->adjustItemSize(ite);
1644 			}
1645 		}
1646 		else if ((command == "u") || (command == "q"))
1647 		{
1648 			QList<PageItem*> gElements;
1649 			groupStack.push(gElements);
1650 			clipStack.push(clipCoords);
1651 		}
1652 		else if ((command == "U") || (command == "Q"))
1653 		{
1654 			if (groupStack.count() != 0)
1655 			{
1656 				QList<PageItem*> gElements = groupStack.pop();
1657 				clipCoords = clipStack.pop();
1658 				tmpSel->clear();
1659 				if (gElements.count() > 0)
1660 				{
1661 					for (int dre = 0; dre < gElements.count(); ++dre)
1662 					{
1663 						tmpSel->addItem(gElements.at(dre), true);
1664 						if (patternMode)
1665 							PatternElements.removeAll(gElements.at(dre));
1666 						else
1667 							Elements.removeAll(gElements.at(dre));
1668 					}
1669 					ite = m_Doc->groupObjectsSelection(tmpSel);
1670 					if ((clipCoords.size() > 4) && (command == "Q"))
1671 					{
1672 						clipCoords.translate(m_Doc->currentPage()->xOffset()-ite->xPos(), m_Doc->currentPage()->yOffset()-ite->yPos());
1673 						ite->PoLine = clipCoords.copy();
1674 						ite->PoLine.translate(baseX, baseY);
1675 					}
1676 					for (int as = 0; as < tmpSel->count(); ++as)
1677 					{
1678 						if (patternMode)
1679 							PatternElements.append(tmpSel->itemAt(as));
1680 						else
1681 							Elements.append(tmpSel->itemAt(as));
1682 					}
1683 				}
1684 				if (groupStack.count() != 0)
1685 				{
1686 					for (int as = 0; as < tmpSel->count(); ++as)
1687 					{
1688 						groupStack.top().append(tmpSel->itemAt(as));
1689 					}
1690 				}
1691 				tmpSel->clear();
1692 			}
1693 			if (command == "Q")
1694 			{
1695 				clipCoords.resize(0);
1696 				clipCoords.svgInit();
1697 			}
1698 		}
1699 		else if (command == "W")
1700 		{
1701 			if (clipStack.count() != 0)
1702 			{
1703 				if (clipStack.top().size() > 3)
1704 				{
1705 					clipStack.top().setMarker();
1706 					clipStack.top().putPoints(clipStack.top().size(), Coords.size(), Coords);
1707 				}
1708 				else
1709 					clipStack.top() = Coords.copy();
1710 			}
1711 		}
1712 		else if ((command == "N") || (command == "n"))
1713 		{
1714 			if (command == "n")
1715 				Coords.svgClosePath();
1716 			currentSpecialPath = Coords.copy();
1717 			Coords.resize(0);
1718 			Coords.svgInit();
1719 		}
1720 /* End Object construction commands */
1721 /* Start Graphics state commands */
1722 		else if (command == "A")
1723 		{
1724 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1725 			ts2 >> tmpInt;
1726 			if (tmpInt == 1)
1727 				itemLocked = true;
1728 			else
1729 				itemLocked = false;
1730 		}
1731 		else if (command == "w")
1732 		{
1733 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1734 			ts2 >> LineW;
1735 		}
1736 		else if (command == "j")
1737 		{
1738 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1739 			ts2 >> tmpInt;
1740 			if (tmpInt == 0)
1741 				JoinStyle = Qt::MiterJoin;
1742 			else if (tmpInt == 1)
1743 				JoinStyle = Qt::RoundJoin;
1744 			else if (tmpInt == 2)
1745 				JoinStyle = Qt::BevelJoin;
1746 		}
1747 		else if (command == "J")
1748 		{
1749 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1750 			ts2 >> tmpInt;
1751 			if (tmpInt == 0)
1752 				CapStyle = Qt::FlatCap;
1753 			else if (tmpInt == 1)
1754 				CapStyle = Qt::RoundCap;
1755 			else if (tmpInt == 2)
1756 				CapStyle = Qt::SquareCap;
1757 		}
1758 		/* undocumented Command Xy
1759 			- has up to 5 Parameters
1760 			- first Parameter might be the Blendmode
1761 			- second Parameter is the Opacity
1762 		*/
1763 		else if (command == "Xy")
1764 		{
1765 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1766 			int mode = 0;
1767 			ts2 >> mode >> Opacity;
1768 			// Adjusting blendmodes, taken from the PDF importer
1769 			switch (mode)
1770 			{
1771 				default:
1772 				case 0:
1773 					blendMode = 0;
1774 					break;
1775 				case 4:
1776 					blendMode = 1;
1777 					break;
1778 				case 5:
1779 					blendMode = 2;
1780 					break;
1781 				case 1:
1782 					blendMode = 3;
1783 					break;
1784 				case 2:
1785 					blendMode = 4;
1786 					break;
1787 				case 3:
1788 					blendMode = 5;
1789 					break;
1790 				case 8:
1791 					blendMode = 6;
1792 					break;
1793 				case 9:
1794 					blendMode = 7;
1795 					break;
1796 				case 10:
1797 					blendMode = 8;
1798 					break;
1799 				case 11:
1800 					blendMode = 9;
1801 					break;
1802 				case 6:
1803 					blendMode = 10;
1804 					break;
1805 				case 7:
1806 					blendMode = 11;
1807 					break;
1808 				case 12:
1809 					blendMode = 12;
1810 					break;
1811 				case 13:
1812 					blendMode = 13;
1813 					break;
1814 				case 14:
1815 					blendMode = 14;
1816 					break;
1817 				case 15:
1818 					blendMode = 15;
1819 					break;
1820 			}
1821 		}
1822 		else if (command == "XR")
1823 		{
1824 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
1825 			ts2 >> tmpInt;
1826 			if (tmpInt == 1)
1827 				fillRule = true;
1828 			else
1829 				fillRule = false;
1830 		}
1831 		else if (command == "Bb")
1832 		{
1833 			gradientMode = true;
1834 			wasBC = false;
1835 			itemRendered = false;
1836 			startMatrix = QTransform();
1837 			endMatrix = QTransform();
1838 		}
1839 		else if (command == "Xm")
1840 		{
1841 			ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
1842 			double m1, m2, m3, m4, m5, m6;
1843 			gVals >> m1 >> m2 >> m3 >> m4 >> m5 >> m6;
1844 			startMatrix.translate(m5, -m6);
1845 			endMatrix.scale(m1, m4);
1846 			wasBC = true;
1847 		}
1848 		else if (command == "Bm")
1849 		{
1850 			if (m_gradients[currentGradientName].type() == 1)
1851 			{
1852 				ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
1853 				double m1, m2, m3, m4, m5, m6;
1854 				gVals >> m1 >> m2 >> m3 >> m4 >> m5 >> m6;
1855 				startMatrix.translate(m5, -m6);
1856 //				endMatrix.scale(m1, m4);
1857 				endMatrix *= QTransform(m1, m2, m3, m4, 0, 0);
1858 //				endMatrix = QTransform(m1, m2, m3, m4, m5, m6);
1859 				wasBC = true;
1860 			}
1861 		}
1862 		else if (command == "BB")
1863 		{
1864 			if (itemRendered)
1865 			{
1866 				gradientMode = false;
1867 				ite = m_Doc->Items->last();
1868 				ite->fill_gradient = m_gradients[currentGradientName];
1869 				ite->setGradient(currentGradientName);
1870 				if (ite->fill_gradient.type() == 0)
1871 					ite->GrType = Gradient_Linear;
1872 				else
1873 					ite->GrType = Gradient_Radial;
1874 				QTransform m1;
1875 				m1.translate(currentGradientOrigin.x() - ite->xPos(), currentGradientOrigin.y() - ite->yPos());
1876 				m1.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1877 				m1.rotate(-currentGradientAngle);
1878 				ite->GrStartX = currentGradientOrigin.x() - ite->xPos() + m_Doc->currentPage()->xOffset();
1879 				ite->GrStartY = currentGradientOrigin.y() - ite->yPos() + m_Doc->currentPage()->yOffset();
1880 				QPointF target = m1.map(QPointF(currentGradientLength, 0.0));
1881 				ite->GrEndX = target.x();
1882 				ite->GrEndY = target.y();
1883 				if (wasBC)
1884 				{
1885 					QPointF newS = startMatrix.map(QPointF(ite->GrStartX, ite->GrStartY));
1886 					ite->GrStartX = newS.x();
1887 					ite->GrStartY = newS.y();
1888 					QTransform m2;
1889 					m2.rotate(-currentGradientAngle);
1890 					m2 *= endMatrix;
1891 					QPointF target = m2.map(QPointF(currentGradientLength, 0.0));
1892 					ite->GrEndX = target.x();
1893 					ite->GrEndY = target.y();
1894 				}
1895 			}
1896 			wasBC = false;
1897 			currentGradientMatrix = QTransform();
1898 			currentGradientOrigin = QPointF(0.0, 0.0);
1899 			currentGradientAngle = 0.0;
1900 			currentGradientLength = 1.0;
1901 			itemRendered = false;
1902 		}
1903 		else if (command == "Bg")
1904 		{
1905 			int an = Cdata.indexOf("(");
1906 			int en = Cdata.lastIndexOf(")");
1907 			currentGradientName = Cdata.mid(an+1, en-an-1);
1908 			currentGradientName.remove("\\");
1909 			QString tmpS = Cdata.mid(en+1, Cdata.size() - en);
1910 			ScTextStream gVals(&tmpS, QIODevice::ReadOnly);
1911 			double xOrig, yOrig, m1, m2, m3, m4, m5, m6;
1912 			gVals >> xOrig >> yOrig >> currentGradientAngle >> currentGradientLength >> m1 >> m2 >> m3 >> m4 >> m5 >> m6;
1913 			currentGradientOrigin = QPointF(xOrig - docX, docHeight - (yOrig - docY));
1914 			currentGradientMatrix = QTransform(m1, m2, m3, m4, m5, m6);
1915 		}
1916 /* End Graphics state commands */
1917 /* Start Color commands */
1918 		else if ((command == "G") || (command == "g"))
1919 		{
1920 			if (command == "G")
1921 				CurrColorStroke = parseColorGray(Cdata);
1922 			else
1923 				CurrColorFill = parseColorGray(Cdata);
1924 			meshColorMode = 2;
1925 		}
1926 		else if ((command == "K") || (command == "k"))
1927 		{
1928 			if (command == "K")
1929 				CurrColorStroke = parseColor(Cdata);
1930 			else
1931 				CurrColorFill = parseColor(Cdata);
1932 		}
1933 		else if ((command == "XA") || (command == "Xa"))
1934 		{
1935 			QString Xdata = da2[da2.count()-4] + " " + da2[da2.count()-3] + " " + da2[da2.count()-2];
1936 			if (command == "XA")
1937 				CurrColorStroke = parseColorRGB(Xdata);
1938 			else
1939 				CurrColorFill = parseColorRGB(Xdata);
1940 			meshColorMode = 1;
1941 		}
1942 		else if ((command == "XX") || (command == "Xx") || (command == "Xk"))
1943 		{
1944 			if (command == "XX")
1945 				CurrColorStroke = parseCustomColorX(Cdata, CurrStrokeShade, da2[da2.count()-2]);
1946 			else
1947 				CurrColorFill = parseCustomColorX(Cdata, CurrFillShade, da2[da2.count()-2]);
1948 		}
1949 		else if ((command == "X") || (command == "x"))
1950 		{
1951 			if (command == "X")
1952 				CurrColorStroke = parseCustomColor(Cdata, CurrStrokeShade);
1953 			else
1954 				CurrColorFill = parseCustomColor(Cdata, CurrFillShade);
1955 		}
1956 		else if (command == "p")
1957 		{
1958 			int an = Cdata.indexOf("(");
1959 			int en = Cdata.lastIndexOf(")");
1960 			currentPatternName = Cdata.mid(an+1, en-an-1);
1961 			currentPatternName.remove("\\");
1962 			currentPatternName = currentPatternName.trimmed().simplified().replace(" ", "_");
1963 			QString tmpS = Cdata.mid(en+1, Cdata.size() - en);
1964 			ScTextStream gVals(&tmpS, QIODevice::ReadOnly);
1965 			gVals >> currentPatternX >> currentPatternY >> currentPatternXScale >> currentPatternYScale >> currentPatternRotation;
1966 		}
1967 		else if (command == "P")
1968 		{
1969 			int an = Cdata.indexOf("(");
1970 			int en = Cdata.lastIndexOf(")");
1971 			currentStrokePatternName = Cdata.mid(an+1, en-an-1);
1972 			currentStrokePatternName.remove("\\");
1973 			currentStrokePatternName = currentPatternName.trimmed().simplified().replace(" ", "_");
1974 			QString tmpS = Cdata.mid(en+1, Cdata.size() - en);
1975 			ScTextStream gVals(&tmpS, QIODevice::ReadOnly);
1976 			gVals >> currentStrokePatternX >> currentStrokePatternY >> currentStrokePatternXScale >> currentStrokePatternYScale >> currentStrokePatternRotation;
1977 		}
1978 		else if (command == "X!")
1979 		{
1980 			if (Cdata.contains("/Mesh"))
1981 			{
1982 				meshMode = true;
1983 				meshNodeCounter = 0;
1984 //				meshColorMode = 0;
1985 				meshGradientArray.clear();
1986 			}
1987 			if (Cdata.contains("/End"))
1988 			{
1989 				meshMode = false;
1990 				if (meshGradientArray.count() != 0)
1991 				{
1992 					z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, CommonStrings::None, CommonStrings::None);
1993 					ite = m_Doc->Items->at(z);
1994 					for (int x = 0; x < meshGradientArray.count(); x++)
1995 					{
1996 						for (int y = 0; y < meshGradientArray[x].count(); y++)
1997 						{
1998 							meshGradientArray[x][y].moveRel(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1999 						}
2000 					}
2001 					ite->meshGradientArray = meshGradientArray;
2002 					ite->GrType = Gradient_Mesh;
2003 					ite->meshToShape();
2004 					for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
2005 					{
2006 						for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
2007 						{
2008 							MeshPoint mp = ite->meshGradientArray[grow][gcol];
2009 							ite->setMeshPointColor(grow, gcol, mp.colorName, mp.shade, mp.transparency);
2010 						}
2011 					}
2012 					ite->setFillShade(CurrFillShade);
2013 					ite->setLineShade(CurrFillShade);
2014 					ite->setFillEvenOdd(fillRule);
2015 					ite->setFillTransparency(1.0 - Opacity);
2016 					ite->setLineTransparency(1.0 - Opacity);
2017 					ite->setFillBlendmode(blendMode);
2018 					ite->setLineBlendmode(blendMode);
2019 					ite->setLineEnd(CapStyle);
2020 					ite->setLineJoin(JoinStyle);
2021 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
2022 						ite->setLocked(itemLocked);
2023 					if (patternMode)
2024 						PatternElements.append(ite);
2025 					else
2026 						Elements.append(ite);
2027 					if (groupStack.count() != 0)
2028 						groupStack.top().append(ite);
2029 				}
2030 			}
2031 		}
2032 		else if (command == "X#")
2033 		{
2034 			int an = Cdata.indexOf("_");
2035 			QString cmdLine = Cdata.remove(0, an+1);
2036 			an = cmdLine.lastIndexOf("/");
2037 			QString tmpS = cmdLine.mid(an+1, Cdata.size());
2038 			ScTextStream mVals(&tmpS, QIODevice::ReadOnly);
2039 			QString mKey;
2040 			mVals >> mKey;
2041 			if (mKey == "Size")
2042 			{
2043 				meshGradientArray.clear();
2044 				int ans = cmdLine.indexOf("[");
2045 				int ens = cmdLine.lastIndexOf("]");
2046 				QString sizeVals = cmdLine.mid(ans+1, ens-ans-1);
2047 				ScTextStream mVals2(&sizeVals, QIODevice::ReadOnly);
2048 				mVals2 >> meshXSize >> meshYSize;
2049 				for (int mgr = 0; mgr < meshYSize+1; mgr++)
2050 				{
2051 					QList<MeshPoint> ml;
2052 					for (int mgc = 0; mgc < meshXSize+1; mgc++)
2053 					{
2054 						MeshPoint mp;
2055 						ml.append(mp);
2056 					}
2057 					meshGradientArray.append(ml);
2058 				}
2059 			}
2060 			if (mKey == "P")
2061 			{
2062 				int ans = cmdLine.indexOf("[");
2063 				int ens = cmdLine.lastIndexOf("]");
2064 				QString posVals = cmdLine.mid(ans+1, ens-ans-1);
2065 				ScTextStream mVals3(&posVals, QIODevice::ReadOnly);
2066 				mVals3 >> currentMeshXPos >> currentMeshYPos;
2067 			}
2068 			if (mKey == "CS")
2069 			{
2070 				if (Cdata.contains("CMYK"))
2071 					meshColorMode = 0;
2072 				else if (Cdata.contains("RGB"))
2073 					meshColorMode = 1;
2074 				else if (Cdata.contains("Gray"))
2075 					meshColorMode = 2;
2076 			}
2077 			if (mKey == "E")
2078 			{
2079 				int indY = meshYSize - currentMeshYPos - 1;
2080 				int indX = currentMeshXPos;
2081 				meshGradientArray[indY+1][indX+1].gridPoint   = FPoint(meshNode2PointX, meshNode2PointY);
2082 				meshGradientArray[indY+1][indX+1].controlTop  = FPoint(meshNode2Control2X, meshNode2Control2Y);
2083 				meshGradientArray[indY+1][indX+1].controlLeft = FPoint(meshNode2Control1X, meshNode2Control1Y);
2084 				meshGradientArray[indY+1][indX+1].colorName = meshColor2;
2085 				meshGradientArray[indY+1][indX+1].shade = 100;
2086 				meshGradientArray[indY+1][indX+1].transparency = 1.0;
2087 				meshGradientArray[indY+1][indX].gridPoint    = FPoint(meshNode1PointX, meshNode1PointY);
2088 				meshGradientArray[indY+1][indX].controlRight = FPoint(meshNode1Control2X, meshNode1Control2Y);
2089 				meshGradientArray[indY+1][indX].controlTop   = FPoint(meshNode1Control1X, meshNode1Control1Y);
2090 				meshGradientArray[indY+1][indX].colorName = meshColor1;
2091 				meshGradientArray[indY+1][indX].shade = 100;
2092 				meshGradientArray[indY+1][indX].transparency = 1.0;
2093 				meshGradientArray[indY][indX].gridPoint     = FPoint(meshNode4PointX, meshNode4PointY);
2094 				meshGradientArray[indY][indX].controlBottom = FPoint(meshNode4Control2X, meshNode4Control2Y);
2095 				meshGradientArray[indY][indX].controlRight  = FPoint(meshNode4Control1X, meshNode4Control1Y);
2096 				meshGradientArray[indY][indX].colorName = meshColor4;
2097 				meshGradientArray[indY][indX].shade = 100;
2098 				meshGradientArray[indY][indX].transparency = 1.0;
2099 				meshGradientArray[indY][indX+1].gridPoint     = FPoint(meshNode3PointX, meshNode3PointY);
2100 				meshGradientArray[indY][indX+1].controlLeft   = FPoint(meshNode3Control2X, meshNode3Control2Y);
2101 				meshGradientArray[indY][indX+1].controlBottom = FPoint(meshNode3Control1X, meshNode3Control1Y);
2102 				meshGradientArray[indY][indX+1].colorName = meshColor3;
2103 				meshGradientArray[indY][indX+1].shade = 100;
2104 				meshGradientArray[indY][indX+1].transparency = 1.0;
2105 				meshNodeCounter = 0;
2106 			}
2107 			if (mKey == "N")
2108 			{
2109 				double cVal {0.0}, mVal {0.0}, yVal {0.0}, kVal {0.0}, coorX1 {0.0}, coorY1 {0.0}, coorX2 {0.0}, coorY2 {0.0}, coorX3 {0.0}, coorY3 {0.0};
2110 				int dummy {0};
2111 				meshNodeCounter++;
2112 				int ans = cmdLine.indexOf("[");
2113 				int ens = cmdLine.lastIndexOf("]");
2114 				QString nodeVals = cmdLine.mid(ans+1, ens-ans-1);
2115 				ScTextStream mVals4(&nodeVals, QIODevice::ReadOnly);
2116 				cVal = 0.0;
2117 				mVal = 0.0;
2118 				yVal = 0.0;
2119 				kVal = 0.0;
2120 				if (meshColorMode == 0)
2121 					mVals4 >> cVal >> mVal >> yVal >> kVal >> coorX1 >> coorY1 >> coorX2 >> coorY2 >> dummy >> coorX3 >> coorY3;
2122 				else if (meshColorMode == 1)
2123 					mVals4 >> cVal >> mVal >> yVal >> coorX1 >> coorY1 >> coorX2 >> coorY2 >> dummy >> coorX3 >> coorY3;
2124 				else if (meshColorMode == 2)
2125 					mVals4 >> cVal >> coorX1 >> coorY1 >> coorX2 >> coorY2 >> dummy >> coorX3 >> coorY3;
2126 				QString nodeColor;
2127 				ScColor tmpColor;
2128 				ColorList::Iterator it;
2129 				int Cc = qRound(cVal * 255);
2130 				int Mc = qRound(mVal * 255);
2131 				int Yc = qRound(yVal * 255);
2132 				int Kc = qRound(kVal * 255);
2133 				int hC, hM, hY, hK;
2134 				bool found = false;
2135 				if (meshColorMode == 0)
2136 				{
2137 					tmpColor.setColor(Cc, Mc, Yc, Kc);
2138 					for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
2139 					{
2140 						if (it.value().getColorModel() == colorModelCMYK)
2141 						{
2142 							it.value().getCMYK(&hC, &hM, &hY, &hK);
2143 							if ((Cc == hC) && (Mc == hM) && (Yc == hY) && (Kc == hK))
2144 							{
2145 								nodeColor = it.key();
2146 								found = true;
2147 								break;
2148 							}
2149 						}
2150 					}
2151 				}
2152 				else if (meshColorMode == 1)
2153 				{
2154 					tmpColor.setRgbColor(Cc, Mc, Yc);
2155 					for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
2156 					{
2157 						if (it.value().getColorModel() == colorModelRGB)
2158 						{
2159 							it.value().getRGB(&hC, &hM, &hY);
2160 							if ((Cc == hC) && (Mc == hM) && (Yc == hY))
2161 							{
2162 								nodeColor = it.key();
2163 								found = true;
2164 								break;
2165 							}
2166 						}
2167 					}
2168 				}
2169 				else if (meshColorMode == 2)
2170 				{
2171 					tmpColor.setColor(0, 0, 0, Cc);
2172 					for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
2173 					{
2174 						if (it.value().getColorModel() == colorModelCMYK)
2175 						{
2176 							it.value().getCMYK(&hC, &hM, &hY, &hK);
2177 							if ((Cc == hC) && (Mc == hM) && (Yc == hY) && (Kc == hK))
2178 							{
2179 								nodeColor = it.key();
2180 								found = true;
2181 								break;
2182 							}
2183 						}
2184 					}
2185 				}
2186 				if (!found)
2187 				{
2188 					tmpColor.setSpotColor(false);
2189 					tmpColor.setRegistrationColor(false);
2190 					QString namPrefix = "FromAI";
2191 					m_Doc->PageColors.insert(namPrefix+tmpColor.name(), tmpColor);
2192 					nodeColor = namPrefix+tmpColor.name();
2193 				}
2194 				if (meshNodeCounter == 1)
2195 				{
2196 					meshNode1PointX = coorX1 - docX;
2197 					meshNode1PointY = docHeight - (coorY1 - docY);
2198 					meshNode1Control2X = coorX2 - docX;
2199 					meshNode1Control2Y = docHeight - (coorY2 - docY);
2200 					meshNode1Control1X = coorX3 - docX;
2201 					meshNode1Control1Y = docHeight - (coorY3 - docY);
2202 					meshColor1 = nodeColor;
2203 				}
2204 				if (meshNodeCounter == 2)
2205 				{
2206 					meshNode2PointX = coorX1 - docX;
2207 					meshNode2PointY = docHeight - (coorY1 - docY);
2208 					meshNode2Control2X = coorX2 - docX;
2209 					meshNode2Control2Y = docHeight - (coorY2 - docY);
2210 					meshNode2Control1X = coorX3 - docX;
2211 					meshNode2Control1Y = docHeight - (coorY3 - docY);
2212 					meshColor2 = nodeColor;
2213 				}
2214 				if (meshNodeCounter == 3)
2215 				{
2216 					meshNode3PointX = coorX1 - docX;
2217 					meshNode3PointY = docHeight - (coorY1 - docY);
2218 					meshNode3Control2X = coorX2 - docX;
2219 					meshNode3Control2Y = docHeight - (coorY2 - docY);
2220 					meshNode3Control1X = coorX3 - docX;
2221 					meshNode3Control1Y = docHeight - (coorY3 - docY);
2222 					meshColor3 = nodeColor;
2223 				}
2224 				if (meshNodeCounter == 4)
2225 				{
2226 					meshNode4PointX = coorX1 - docX;
2227 					meshNode4PointY = docHeight - (coorY1 - docY);
2228 					meshNode4Control2X = coorX2 - docX;
2229 					meshNode4Control2Y = docHeight - (coorY2 - docY);
2230 					meshNode4Control1X = coorX3 - docX;
2231 					meshNode4Control1Y = docHeight - (coorY3 - docY);
2232 					meshColor4 = nodeColor;
2233 				}
2234 			}
2235 		}
2236 /* End Color commands */
2237 /* Start Layer commands */
2238 		else if (command == "Lb")
2239 		{
2240 			if (importerFlags & LoadSavePlugin::lfCreateDoc)
2241 			{
2242 				int visible, preview, enabled, printing, dummy, rc, gc, bc;
2243 				ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
2244 				ts2 >> visible >> preview >> enabled >> printing >> dummy >> dummy >> dummy >> rc >> gc >> bc;
2245 				if (!firstLayer)
2246 					currentLayer = m_Doc->addLayer("Layer", true);
2247 				m_Doc->setLayerVisible(currentLayer, static_cast<bool>(visible));
2248 				m_Doc->setLayerOutline(currentLayer, static_cast<bool>(!preview));
2249 				m_Doc->setLayerLocked(currentLayer, static_cast<bool>(!enabled));
2250 				m_Doc->setLayerPrintable(currentLayer, static_cast<bool>(printing));
2251 				m_Doc->setLayerMarker(currentLayer, QColor(rc, gc, bc));
2252 				QList<PageItem*> gElements;
2253 				groupStack.push(gElements);
2254 				clipStack.push(clipCoords);
2255 				firstLayer = false;
2256 			}
2257 			Coords.resize(0);
2258 			Coords.svgInit();
2259 		}
2260 		else if (command == "LB")
2261 		{
2262 			if (importerFlags & LoadSavePlugin::lfCreateDoc)
2263 			{
2264 				if (groupStack.count() != 0)
2265 				{
2266 					QList<PageItem*> gElements = groupStack.pop();
2267 					clipStack.pop();
2268 					tmpSel->clear();
2269 					if (gElements.count() > 0)
2270 					{
2271 						for (int dre = 0; dre < gElements.count(); ++dre)
2272 						{
2273 							tmpSel->addItem(gElements.at(dre), true);
2274 							if (patternMode)
2275 								PatternElements.removeAll(gElements.at(dre));
2276 							else
2277 								Elements.removeAll(gElements.at(dre));
2278 						}
2279 						m_Doc->groupObjectsSelection(tmpSel);
2280 						ite = tmpSel->itemAt(0);
2281 						if (Coords.size() > 3)
2282 						{
2283 							Coords.translate(m_Doc->currentPage()->xOffset()-ite->xPos(), m_Doc->currentPage()->yOffset()-ite->yPos());
2284 							ite->PoLine = Coords.copy();
2285 							ite->PoLine.translate(baseX, baseY);
2286 						}
2287 						for (int as = 0; as < tmpSel->count(); ++as)
2288 						{
2289 							if (patternMode)
2290 								PatternElements.append(tmpSel->itemAt(as));
2291 							else
2292 								Elements.append(tmpSel->itemAt(as));
2293 						}
2294 						ite->setItemName( tr("Group%1").arg(m_Doc->layerName(currentLayer)));
2295 					}
2296 					if (groupStack.count() != 0)
2297 					{
2298 						for (int as = 0; as < tmpSel->count(); ++as)
2299 						{
2300 							groupStack.top().append(tmpSel->itemAt(as));
2301 						}
2302 					}
2303 					tmpSel->clear();
2304 				}
2305 			}
2306 			Coords.resize(0);
2307 			Coords.svgInit();
2308 		}
2309 		else if (command == "Ln")
2310 		{
2311 			if (importerFlags & LoadSavePlugin::lfCreateDoc)
2312 			{
2313 				int an = Cdata.indexOf("(");
2314 				int en = Cdata.lastIndexOf(")");
2315 				QString LayerNam = Cdata.mid(an+1, en-an-1);
2316 				LayerNam.remove("\\");
2317 				m_Doc->changeLayerName(currentLayer, LayerNam);
2318 			}
2319 		}
2320 /* End Layer commands */
2321 /* Start Text commands */
2322 		else if (command == "To")
2323 		{
2324 			ScTextStream ts2(&Cdata, QIODevice::ReadOnly);
2325 			ts2 >> textMode;
2326 			textData.clear();
2327 			textMatrix = QTransform();
2328 			maxWidth = 0;
2329 			tempW = 0;
2330 			maxHeight = 0;
2331 			textKern = 0;
2332 			startCurrentTextRange = 0;
2333 			endCurrentTextRange = 0;
2334 			textScaleH = 1000;
2335 			textScaleV = 1000;
2336 		}
2337 		else if (command == "Tp")
2338 		{
2339 			ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
2340 			double m1, m2, m3, m4, m5, m6;
2341 			gVals >> m1 >> m2 >> m3 >> m4 >> m5 >> m6;
2342 			textMatrix = QTransform(m1, m2, m3, m4, m5, m6);
2343 		}
2344 		else if (command == "Tx") // || (command == "TX"))
2345 		{
2346 			QStringList res = getStrings(Cdata);
2347 			if (res.count() > 0)
2348 			{
2349 				QString tex = res[0];
2350 				double tempH = 0;
2351 				startCurrentTextRange = textData.length();
2352 				for (int tt = 0; tt < tex.length(); ++tt)
2353 				{
2354 					CharStyle nstyle;
2355 					QString ch = tex.mid(tt,1);
2356 					nstyle.setFont((*m_Doc->AllFonts)[textFont]);
2357 					nstyle.setFontSize(textSize);
2358 					nstyle.setFillColor(CurrColorFill);
2359 					nstyle.setTracking(textKern);
2360 					nstyle.setFillShade(100);
2361 					nstyle.setStrokeColor(CurrColorStroke);
2362 					nstyle.setStrokeShade(100);
2363 					nstyle.setScaleH(textScaleH);
2364 					nstyle.setScaleV(textScaleV);
2365 					nstyle.setBaselineOffset(0);
2366 					nstyle.setShadowXOffset(50);
2367 					nstyle.setShadowYOffset(-50);
2368 					nstyle.setOutlineWidth(10);
2369 					nstyle.setUnderlineOffset(-1);
2370 					nstyle.setUnderlineWidth(-1);
2371 					nstyle.setStrikethruOffset(-1);
2372 					nstyle.setStrikethruWidth(-1);
2373 					nstyle.setFeatures(StyleFlag(ScStyle_Default).featureList());
2374 					int pot = textData.length();
2375 					textData.insertChars(pot, ch);
2376 					textData.applyCharStyle(pot, 1, nstyle);
2377 					// FIXME HOST: This code does not handle CTL!
2378 					ScFace::gid_type gid = nstyle.font().char2CMap(ch.toUcs4()[0]);
2379 					tempW += nstyle.font().glyphBBox(gid, nstyle.fontSize() / 10.0).width + 1;
2380 					tempH  = qMax(tempH, nstyle.font().height(nstyle.fontSize() / 10.0) + 2.0);
2381 					maxWidth  = qMax(tempW, maxWidth);
2382 					maxHeight = qMax(tempH, maxHeight);
2383 					if ((ch == SpecialChars::PARSEP) || (ch == SpecialChars::LINEBREAK))
2384 					{
2385 						maxHeight += nstyle.font().height(nstyle.fontSize() / 10.0);
2386 						tempW = 0;
2387 					}
2388 					endCurrentTextRange = pot;
2389 				}
2390 			}
2391 		}
2392 		else if (command == "Tk")
2393 		{
2394 			int flag;
2395 			double val;
2396 			ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
2397 			gVals >> flag >> val;
2398 			if (flag == 1)
2399 				val = 0;
2400 			double oldval = textData.charStyle(startCurrentTextRange).tracking();
2401 			CharStyle nstyle = textData.charStyle(startCurrentTextRange);
2402 			nstyle.setTracking(oldval + val);
2403 			textData.applyCharStyle(startCurrentTextRange, 1, nstyle);
2404 		}
2405 		else if (command == "Tc")
2406 		{
2407 			ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
2408 			gVals >> textKern;
2409 			textKern *= 100.0;
2410 		}
2411 		else if (command == "Tz")
2412 		{
2413 			ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
2414 			gVals >> textScaleH >> textScaleV;
2415 			textScaleH *= 10.0;
2416 			textScaleV *= 10.0;
2417 		}
2418 		else if (command == "T*")
2419 		{
2420 			CharStyle nstyle;
2421 			QString ch = SpecialChars::LINEBREAK;
2422 			nstyle.setFont((*m_Doc->AllFonts)[textFont]);
2423 			nstyle.setFontSize(textSize);
2424 			nstyle.setFillColor(CurrColorFill);
2425 			nstyle.setTracking(textKern);
2426 			nstyle.setFillShade(100);
2427 			nstyle.setStrokeColor(CurrColorStroke);
2428 			nstyle.setStrokeShade(100);
2429 			nstyle.setScaleH(textScaleH);
2430 			nstyle.setScaleV(textScaleV);
2431 			nstyle.setBaselineOffset(0);
2432 			nstyle.setShadowXOffset(50);
2433 			nstyle.setShadowYOffset(-50);
2434 			nstyle.setOutlineWidth(10);
2435 			nstyle.setUnderlineOffset(-1);
2436 			nstyle.setUnderlineWidth(-1);
2437 			nstyle.setStrikethruOffset(-1);
2438 			nstyle.setStrikethruWidth(-1);
2439 			nstyle.setFeatures(StyleFlag(ScStyle_Default).featureList());
2440 			int pot = textData.length();
2441 			textData.insertChars(pot, ch);
2442 			textData.applyCharStyle(pot, 1, nstyle);
2443 			maxHeight += nstyle.font().height(nstyle.fontSize() / 10.0) + 2.0;
2444 			tempW = 0;
2445 		}
2446 		else if (command == "Tf")
2447 		{
2448 			ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
2449 			gVals >> textFont >> textSize;
2450 			textFont.remove(0, 2);
2451 			QString family = textFont;
2452 			QString ret = "";
2453 			family.replace( QRegExp( "'" ) , QChar( ' ' ) );
2454 			textFont = m_Doc->itemToolPrefs().textFont;
2455 			bool found = false;
2456 			SCFontsIterator it(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts);
2457 			for ( ; it.hasNext(); it.next())
2458 			{
2459 				QString fam;
2460 				QString fn = it.current().scName();
2461 				int pos = fn.indexOf(" ");
2462 				fam = fn.left(pos);
2463 				if (fam == family)
2464 				{
2465 					found = true;
2466 					ret = fn;
2467 				}
2468 			}
2469 			if (found)
2470 				textFont = family;
2471 			else
2472 			{
2473 				if (importerFlags & LoadSavePlugin::lfCreateThumbnail)
2474 					textFont = PrefsManager::instance().appPrefs.itemToolPrefs.textFont;
2475 				else
2476 				{
2477 					if (!PrefsManager::instance().appPrefs.fontPrefs.GFontSub.contains(family))
2478 					{
2479 						qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
2480 						MissingFont *dia = new MissingFont(nullptr, family, m_Doc);
2481 						dia->exec();
2482 						QString tmpf = dia->getReplacementFont();
2483 						delete dia;
2484 						qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
2485 						PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family] = tmpf;
2486 					}
2487 					else
2488 						textFont = PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family];
2489 				}
2490 			}
2491 			textSize *= 10.0;
2492 		}
2493 		else if (command == "TO")
2494 		{
2495 			if (textData.length() > 0)
2496 			{
2497 				if (!((textData.length() == 1) && (textData.text(0) == SpecialChars::PARSEP)))
2498 				{
2499 					QPointF pos = QPointF(textMatrix.dx(), textMatrix.dy());
2500 					pos += QPointF(m_Doc->currentPage()->xOffset(), -m_Doc->currentPage()->yOffset());
2501 					pos += QPointF(0.0, textSize / 10.0 + 2.0);
2502 					z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, pos.x() - docX, docHeight - (pos.y() - docY), 10, 10, 0, CommonStrings::None, CommonStrings::None);
2503 					ite = m_Doc->Items->at(z);
2504 					ite->setTextToFrameDist(0.0, 0.0, 0.0, 0.0);
2505 					ite->itemText.append(textData);
2506 					ite->itemText.trim();
2507 					double xpos = ite->xPos();
2508 					double ypos = ite->yPos();
2509 					ite->setWidthHeight(qMax(ite->width(), maxWidth), qMax(ite->height(), maxHeight));
2510 					double xoffset = 0.0, yoffset = 0.0;
2511 					double rotation = getRotationFromMatrix(textMatrix, 0.0);
2512 					if (rotation != 0.0)
2513 					{
2514 						double temp = textSize / 10.0 + 2.0;
2515 						xoffset = sin(rotation) * temp;
2516 						yoffset = cos(rotation) * temp;
2517 					}
2518 					ite->setXPos(xpos + xoffset);
2519 					ite->setYPos(ypos + yoffset);
2520 					ite->setRotation(rotation * 180 / M_PI);
2521 					ite->SetRectFrame();
2522 					m_Doc->setRedrawBounding(ite);
2523 					ite->Clip = flattenPath(ite->PoLine, ite->Segments);
2524 					ite->setTextFlowMode(PageItem::TextFlowDisabled);
2525 					ite->setFillShade(CurrFillShade);
2526 					ite->setLineShade(CurrStrokeShade);
2527 					ite->setFillEvenOdd(fillRule);
2528 					ite->setFillTransparency(1.0 - Opacity);
2529 					ite->setLineTransparency(1.0 - Opacity);
2530 					ite->setLineEnd(CapStyle);
2531 					ite->setLineJoin(JoinStyle);
2532 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
2533 						ite->setLocked(itemLocked);
2534 					if (patternMode)
2535 						PatternElements.append(ite);
2536 					else
2537 						Elements.append(ite);
2538 					if (groupStack.count() != 0)
2539 						groupStack.top().append(ite);
2540 				}
2541 			}
2542 		}
2543 /* End Text commands */
2544 /* Start special Commands */
2545 		else if (command == "*")
2546 		{
2547 			Coords.resize(0);
2548 			Coords.svgInit();
2549 		}
2550 		else if (command == "[")
2551 		{
2552 			Coords.resize(0);
2553 			Coords.svgInit();
2554 			int an = Cdata.indexOf("(");
2555 			int en = Cdata.lastIndexOf(")");
2556 			if ((an != -1) && (en != -1))
2557 			{
2558 				patternMode = true;
2559 				currentPatternDefName = Cdata.mid(an+1, en-an-1);
2560 				currentPatternDefName.remove("\\");
2561 				currentPatternDefName = currentPatternDefName.trimmed().simplified().replace(" ", "_");
2562 				QString tmpS = Cdata.mid(en+1, Cdata.size() - en);
2563 				ScTextStream gVals(&tmpS, QIODevice::ReadOnly);
2564 				gVals >> patternX1 >> patternY1 >> patternX2 >> patternY2;
2565 			}
2566 		}
2567 		else if (command == ",")
2568 		{
2569 			if (Cdata.contains("/Data"))
2570 			{
2571 				dataMode = true;
2572 				dataString = "";
2573 			}
2574 		}
2575 		else if (command == ":")
2576 		{
2577 			fObjectMode = true;
2578 		}
2579 /* End special Commands */
2580 /* Skip everything else */
2581 //		else
2582 //			qDebug() << command;
2583 	}
2584 }
2585 
processGradientData(const QString & data)2586 void AIPlug::processGradientData(const QString& data)
2587 {
2588 	QString command;
2589 	QString Cdata;
2590 	QStringList da;
2591 	getCommands(data, da);
2592 	for (int a = 0; a < da.count(); a++)
2593 	{
2594 		Cdata = da[a];
2595 		QStringList da2 = Cdata.split(" ", Qt::SkipEmptyParts);
2596 		command = da2.last();
2597 		if (command == "Bd")
2598 		{
2599 			int an = Cdata.indexOf("(");
2600 			int en = Cdata.lastIndexOf(")");
2601 			currentGradientName = Cdata.mid(an+1, en-an-1);
2602 			currentGradientName.remove("\\");
2603 			if (da2[da2.count()-3] == "0")
2604 				currentGradient = VGradient(VGradient::linear);
2605 			else
2606 				currentGradient = VGradient(VGradient::radial);
2607 			currentGradient.clearStops();
2608 		}
2609 		else if ((command == "%_Bs") || (command == "%_BS"))
2610 		{
2611 			QString stopName = "";
2612 			double stop = ScCLocale::toDoubleC(da2[da2.count()-2]) / 100.0;
2613 			double colorShade = 100.0;
2614 			int colortype = da2[da2.count()-4].toInt();
2615 			if (colortype == 0)
2616 			{
2617 				stopName = parseColorGray(Cdata);
2618 				const ScColor& gradC = m_Doc->PageColors[stopName];
2619 				currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), stop, 0.5, 1.0, stopName, 100 );
2620 			}
2621 			else if (colortype == 1)
2622 			{
2623 				stopName = parseColor(Cdata);
2624 				const ScColor& gradC = m_Doc->PageColors[stopName];
2625 				currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), stop, 0.5, 1.0, stopName, 100 );
2626 			}
2627 			else if (colortype == 2)
2628 			{
2629 				stopName = parseColor(Cdata);
2630 				const ScColor& gradC = m_Doc->PageColors[stopName];
2631 				currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), stop, 0.5, 1.0, stopName, 100 );
2632 			}
2633 			else if (colortype == 3)
2634 			{
2635 				stopName = parseCustomColor(Cdata, colorShade);
2636 				int stopShade = qRound(colorShade);
2637 				const ScColor& gradC = m_Doc->PageColors[stopName];
2638 				currentGradient.addStop( ScColorEngine::getShadeColor(gradC, m_Doc, stopShade), stop, 0.5, 1.0, stopName, stopShade);
2639 			}
2640 			else if (colortype == 4)
2641 			{
2642 				stopName = parseCustomColorX(Cdata, colorShade, "0");
2643 				int stopShade = qRound(colorShade);
2644 				const ScColor& gradC = m_Doc->PageColors[stopName];
2645 				currentGradient.addStop( ScColorEngine::getShadeColor(gradC, m_Doc, stopShade), stop, 0.5, 1.0, stopName, stopShade);
2646 			}
2647 			else if (colortype == 6)
2648 			{
2649 				stopName = parseColor(Cdata);
2650 				const ScColor& gradC = m_Doc->PageColors[stopName];
2651 				currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), stop, 0.5, 1.0, stopName, 100 );
2652 			}
2653 		}
2654 		else if (command == "BD")
2655 		{
2656 			m_gradients.insert(currentGradientName, currentGradient);
2657 			if (m_Doc->addGradient(currentGradientName, currentGradient))
2658 				importedGradients.append(currentGradientName);
2659 			currentGradient = VGradient(VGradient::linear);
2660 			currentGradient.clearStops();
2661 			currentGradient.setRepeatMethod( VGradient::none );
2662 			currentGradientName = "";
2663 		}
2664 	}
2665 }
2666 
processPattern(QDataStream & ts)2667 void AIPlug::processPattern(QDataStream &ts)
2668 {
2669 	QString tmp = "";
2670 	QString tmpData = "";
2671 	while (!ts.atEnd())
2672 	{
2673 		tmp = removeAIPrefix(readLineFromDataStream(ts));
2674 		if (importerFlags & LoadSavePlugin::lfKeepPatterns)
2675 		{
2676 			if (tmp.startsWith("%_"))
2677 				tmp.remove(0, 2);
2678 		}
2679 		if (patternMode)
2680 		{
2681 			if (tmp == "EndPattern")
2682 			{
2683 				tmpSel->clear();
2684 				if (PatternElements.count() > 0)
2685 				{
2686 					for (int dre = 0; dre < PatternElements.count(); ++dre)
2687 					{
2688 						tmpSel->addItem(PatternElements.at(dre), true);
2689 						if (groupStack.count() != 0)
2690 							groupStack.top().removeAll(PatternElements.at(dre));
2691 					}
2692 					if (PatternElements.count() > 1)
2693 						m_Doc->itemSelection_GroupObjects(false, false, tmpSel);
2694 					if ((tmpSel->width() > 1) && (tmpSel->height() > 1))
2695 					{
2696 						ScPattern pat = ScPattern();
2697 						pat.setDoc(m_Doc);
2698 						PageItem* currItem = tmpSel->itemAt(0);
2699 						currItem->setItemName(currentPatternDefName);
2700 						m_Doc->DoDrawing = true;
2701 						QImage tmpImg = currItem->DrawObj_toImage(qMin(qMax(qRound(patternX2 - patternX1), qRound(patternY2 - patternY1)), 500));
2702 						if (!tmpImg.isNull())
2703 						{
2704 							QImage retImg = QImage(qRound(patternX2 - patternX1), qRound(patternY2 - patternY1), QImage::Format_ARGB32_Premultiplied);
2705 							retImg.fill( qRgba(255, 255, 255, 0) );
2706 							QPainter p;
2707 							p.begin(&retImg);
2708 							if (PatternElements.count() > 1)
2709 								p.drawImage(qRound(-patternX1), qRound(-patternY1), tmpImg);
2710 							else
2711 								p.drawImage(0, 0, tmpImg);
2712 							p.end();
2713 							pat.pattern = retImg;
2714 							m_Doc->DoDrawing = false;
2715 							pat.width = patternX2 - patternX1;
2716 							pat.height = patternY2 - patternY1;
2717 							pat.xoffset = -patternX1;
2718 							pat.yoffset = -patternY1;
2719 							for (int as = 0; as < tmpSel->count(); ++as)
2720 							{
2721 								PageItem* Neu = tmpSel->itemAt(as);
2722 								Neu->moveBy(-patternX1, -patternY1, true);
2723 								Neu->gXpos -= patternX1;
2724 								Neu->gYpos -= patternY1;
2725 								pat.items.append(Neu);
2726 							}
2727 							m_Doc->addPattern(currentPatternDefName, pat);
2728 							importedPatterns.append(currentPatternDefName);
2729 						/*	double minx =  std::numeric_limits<double>::max();
2730 							double miny =  std::numeric_limits<double>::max();
2731 							double maxx = -std::numeric_limits<double>::max();
2732 							double maxy = -std::numeric_limits<double>::max();
2733 							double x1, x2, y1, y2;
2734 							currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
2735 							minx = qMin(minx, x1);
2736 							miny = qMin(miny, y1);
2737 							maxx = qMax(maxx, x2);
2738 							maxy = qMax(maxy, y2);
2739 							currItem->gXpos = currItem->xPos() - minx;
2740 							currItem->gYpos = currItem->yPos() - miny;
2741 							currItem->setXYPos(currItem->gXpos, currItem->gYpos, true);
2742 							m_Doc->docPatterns[currentPatternDefName].width = maxx - minx;
2743 							m_Doc->docPatterns[currentPatternDefName].height = maxy - miny;*/
2744 						}
2745 					}
2746 					m_Doc->itemSelection_DeleteItem(tmpSel);
2747 				}
2748 				PatternElements.clear();
2749 				currentPatternDefName = "";
2750 				break;
2751 			}
2752 			if (tmp.startsWith("Tile"))
2753 				continue;
2754 			if (tmp.contains(") @"))
2755 			{
2756 				tmpData += tmp;
2757 				tmpData.remove(") @");
2758 				processData(tmpData);
2759 				tmpData = "";
2760 			}
2761 			else if (tmp.contains(") &"))
2762 			{
2763 				tmpData += tmp;
2764 				tmpData.remove(") &");
2765 				processData(tmpData);
2766 				tmpData = "";
2767 			}
2768 			else if (tmp.startsWith("("))
2769 			{
2770 				if (tmp.startsWith("("))
2771 					tmp.remove(0, 1);
2772 				tmpData += " "+tmp;
2773 			}
2774 			else
2775 				processData(tmp);
2776 		}
2777 		else if (tmp == "EndPattern")
2778 		{
2779 			PatternElements.clear();
2780 			currentPatternDefName = "";
2781 			break;
2782 		}
2783 		else if (tmp.contains("BeginRaster") && (tmp.startsWith("%")))
2784 		{
2785 			while (!ts.atEnd())
2786 			{
2787 				tmp = readLineFromDataStream(ts);
2788 				if (tmp.contains("EndRaster"))
2789 					break;
2790 				if (progressDialog)
2791 				{
2792 					progressDialog->setProgress("GI", ts.device()->pos());
2793 					qApp->processEvents();
2794 				}
2795 			}
2796 		}
2797 		else
2798 		{
2799 			Coords.resize(0);
2800 			Coords.svgInit();
2801 			int an = tmp.indexOf("(");
2802 			int en = tmp.lastIndexOf(")");
2803 			if ((an != -1) && (en != -1))
2804 			{
2805 				patternMode = true;
2806 				currentPatternDefName = tmp.mid(an+1, en-an-1);
2807 				currentPatternDefName.remove("\\");
2808 				currentPatternDefName = currentPatternDefName.trimmed().simplified().replace(" ", "_");
2809 				QString tmpS = tmp.mid(en+1, tmp.size() - en);
2810 				ScTextStream gVals(&tmpS, QIODevice::ReadOnly);
2811 				gVals >> patternX1 >> patternY1 >> patternX2 >> patternY2;
2812 			}
2813 		}
2814 	//		processData(tmp);
2815 	}
2816 	patternMode = false;
2817 }
2818 
processSymbol(QDataStream & ts,bool sym)2819 void AIPlug::processSymbol(QDataStream &ts, bool sym)
2820 {
2821 	QString tmp;
2822 	while (!ts.atEnd())
2823 	{
2824 		tmp = removeAIPrefix(readLineFromDataStream(ts));
2825 		if (!patternMode)
2826 		{
2827 			int an = tmp.indexOf("(");
2828 			int en = tmp.lastIndexOf(")");
2829 			if ((an != -1) && (en != -1))
2830 			{
2831 				patternMode = true;
2832 				currentPatternDefName = tmp.mid(an+1, en-an-1);
2833 				currentPatternDefName.remove("\\");
2834 				if (sym)
2835 					currentPatternDefName = "S_"+currentPatternDefName.trimmed().simplified().replace(" ", "_");
2836 				else
2837 					currentPatternDefName = currentPatternDefName.trimmed().simplified().replace(" ", "_");
2838 			}
2839 		}
2840 		else if ((tmp == "EndSymbol") || (tmp == "EndBrushPattern"))
2841 		{
2842 			tmpSel->clear();
2843 			if (PatternElements.count() > 0)
2844 			{
2845 				for (int dre = 0; dre < PatternElements.count(); ++dre)
2846 				{
2847 					tmpSel->addItem(PatternElements.at(dre), true);
2848 					groupStack.top().removeAll(PatternElements.at(dre));
2849 				}
2850 				if (PatternElements.count() > 1)
2851 					m_Doc->itemSelection_GroupObjects(false, false, tmpSel);
2852 				if ((tmpSel->width() > 1) && (tmpSel->height() > 1))
2853 				{
2854 					ScPattern pat = ScPattern();
2855 					pat.setDoc(m_Doc);
2856 					PageItem* currItem = tmpSel->itemAt(0);
2857 					currItem->setItemName(currentPatternDefName);
2858 					m_Doc->DoDrawing = true;
2859 					pat.pattern = currItem->DrawObj_toImage(qMin(qMax(tmpSel->width(), tmpSel->height()), 500.0));
2860 					if (!pat.pattern.isNull())
2861 					{
2862 						pat.width = tmpSel->width();
2863 						pat.height = tmpSel->height();
2864 						m_Doc->DoDrawing = false;
2865 						for (int as = 0; as < tmpSel->count(); ++as)
2866 						{
2867 							PageItem* Neu = tmpSel->itemAt(as);
2868 							pat.items.append(Neu);
2869 						}
2870 						importedPatterns.append(currentPatternDefName);
2871 						importedSymbols.insert(currentPatternDefName, QPointF(currItem->xPos(), currItem->yPos()));
2872 						m_Doc->addPattern(currentPatternDefName, pat);
2873 					}
2874 				}
2875 				m_Doc->itemSelection_DeleteItem(tmpSel);
2876 			}
2877 			PatternElements.clear();
2878 			currentPatternDefName = "";
2879 			break;
2880 		}
2881 		else if (tmp.contains("BeginRaster") && (tmp.startsWith("%")))
2882 		{
2883 			while (!ts.atEnd())
2884 			{
2885 				tmp = readLineFromDataStream(ts);
2886 				if (tmp.contains("EndRaster"))
2887 					break;
2888 				if (progressDialog)
2889 				{
2890 					progressDialog->setProgress("GI", ts.device()->pos());
2891 					qApp->processEvents();
2892 				}
2893 			}
2894 		}
2895 		else
2896 		{
2897 			processData(tmp);
2898 		}
2899 	}
2900 	patternMode = false;
2901 }
2902 
processRaster(QDataStream & ts)2903 void AIPlug::processRaster(QDataStream &ts)
2904 {
2905 	double m1, m2, m3, m4, m5, m6, x1, y1, x2, y2, dummy;
2906 	int w, h, type, alpha, bin, bits;
2907 	QString tmp = "";
2908 	QString cumulated = "";
2909 	while (!ts.atEnd())
2910 	{
2911 		tmp = readLineFromDataStream(ts);
2912 		if (tmp.startsWith("%"))
2913 			break;
2914 		tmp.remove("[");
2915 		tmp.remove("]");
2916 		if (!tmp.isEmpty())
2917 			cumulated += " " + tmp;
2918 	}
2919 	QString Cdata = "";
2920 	QStringList da;
2921 	getCommands(cumulated, da);
2922 	Cdata = da.last();
2923 	ScTextStream gVals(&Cdata, QIODevice::ReadOnly);
2924 	gVals >> m1 >> m2 >> m3 >> m4 >> m5 >> m6 >> x1 >> y1 >> x2 >> y2 >> w >> h >> bits >> type >> alpha >> dummy >> bin;
2925 //	qDebug() << QString("Matrix: %1 %2 %3 %4 %5 %6").arg(m1).arg(m2).arg(m3).arg(m4).arg(m5).arg(m6);
2926 //	qDebug() << QString("Bounds: %1 %2 %3 %4").arg(x1).arg(y1).arg(x2).arg(y2);
2927 //	qDebug() << QString("Size: %1 %2").arg(w).arg(h);
2928 //	qDebug() << QString("Bits: %1").arg(bits);
2929 //	qDebug() << QString("Typ: %1").arg(type);
2930 //	qDebug() << QString("Alpha-Channels: %1").arg(alpha);
2931 //	qDebug() << QString("Encoding: %1").arg(bin);
2932 	uint dataSize = w * h * (type + alpha);
2933 	uint alphaData = w * h * type;
2934 //	bool cmyk = false;
2935 //	if (type == 4)
2936 //		cmyk = true;
2937 	if (tmp.startsWith("%%BeginData"))
2938 	{
2939 		ScTextStream gVals2(&tmp, QIODevice::ReadOnly);
2940 		tmp = readLineFromDataStream(ts);
2941 	}
2942 	QByteArray psdata;
2943 	psdata.resize(dataSize);
2944 	RawImage m_image;
2945 	if (type == 4)
2946 	{
2947 		if (alpha > 0)
2948 			m_image.create(w, 1, 5);
2949 		else
2950 			m_image.create(w, 1, 4);
2951 	}
2952 	else
2953 	{
2954 		if (alpha > 0)
2955 			m_image.create(w, 1, 4);
2956 		else
2957 			m_image.create(w, 1, 3);
2958 	}
2959 	bool first = false;
2960 	if (bin == 0) // 0 = ASCII encoded data
2961 	{
2962 		uint dataPointer = 0;
2963 		while (!ts.atEnd())
2964 		{
2965 			if (first)
2966 				tmp = readLineFromDataStream(ts);
2967 			first = true;
2968 			if (tmp.startsWith("%AI5_EndRaster"))
2969 				break;
2970 			for (int a = 1; a < tmp.length(); a += 2)
2971 			{
2972 				bool ok;
2973 				ushort data = tmp.midRef(a, 2).toUShort(&ok, 16);
2974 				psdata[dataPointer++] = data;
2975 			}
2976 		}
2977 	}
2978 	else
2979 	{
2980 		psdata.resize(dataSize);
2981 		ts.readRawData(psdata.data(), dataSize);
2982 	}
2983 	QTransform imgMatrix = QTransform(m1, m2, m3, m4, m5, m6);
2984 	QPointF pos = QPointF(imgMatrix.dx(), imgMatrix.dy());
2985 	pos += QPointF(m_Doc->currentPage()->xOffset(), -m_Doc->currentPage()->yOffset());
2986 	pos += QPointF(baseX, -baseY);
2987 	int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, pos.x() - docX, docHeight - (pos.y() - docY), 10, 10, 0, CurrColorFill, CurrColorStroke);
2988 	PageItem* ite = m_Doc->Items->at(z);
2989 	ite->setWidthHeight(fabs(w * m1), fabs(h * m4));
2990 	double rotation = getRotationFromMatrix(imgMatrix, 0.0);
2991 	ite->setRotation(rotation * 180 / M_PI);
2992 	ite->SetRectFrame();
2993 	m_Doc->setRedrawBounding(ite);
2994 	ite->Clip = flattenPath(ite->PoLine, ite->Segments);
2995 	ite->setTextFlowMode(PageItem::TextFlowDisabled);
2996 	ite->setFillShade(CurrFillShade);
2997 	ite->setLineShade(CurrStrokeShade);
2998 	ite->setFillEvenOdd(fillRule);
2999 	ite->setFillTransparency(1.0 - Opacity);
3000 	ite->setLineTransparency(1.0 - Opacity);
3001 	ite->setFillBlendmode(blendMode);
3002 	ite->setLineBlendmode(blendMode);
3003 	ite->setLineEnd(CapStyle);
3004 	ite->setLineJoin(JoinStyle);
3005 	uchar *p;
3006 	uint yCount = 0;
3007 	quint16 eTag = EXTRASAMPLE_UNASSALPHA;
3008 	QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_ai_XXXXXX.tif");
3009 	tempFile->setAutoRemove(false);
3010 	tempFile->open();
3011 	QString imgName = getLongPathName(tempFile->fileName());
3012 	tempFile->close();
3013 	ite->isInlineImage = true;
3014 	ite->isTempFile = true;
3015 	delete tempFile;
3016 	TIFF* tif = TIFFOpen(imgName.toLocal8Bit().data(), "w");
3017 	if (tif)
3018 	{
3019 		TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
3020 		TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
3021 		TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
3022 		TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, m_image.channels());
3023 		if (alpha == 1)
3024 			TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &eTag);
3025 		TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
3026 		if (type == 4)
3027 			TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED);
3028 		else
3029 			TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
3030 		TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
3031 		for (int y = 0; y < h; ++y)
3032 		{
3033 			p = m_image.scanLine( 0 );
3034 			for (int xh = 0; xh < m_image.width(); ++xh )
3035 			{
3036 				p[0] = psdata[yCount++];
3037 				if (type > 1)
3038 				{
3039 					p[1] = psdata[yCount++];
3040 					p[2] = psdata[yCount++];
3041 					if (type == 4)
3042 						p[3] = psdata[yCount++];
3043 				}
3044 				else
3045 				{
3046 					p[1] = p[0];
3047 					p[2] = p[0];
3048 				}
3049 				if (alpha == 1)
3050 				{
3051 					if (type == 4)
3052 						p[4] = psdata[alphaData++];
3053 					else
3054 						p[3] = psdata[alphaData++];
3055 				}
3056 				p += m_image.channels();
3057 			}
3058 			TIFFWriteScanline(tif, m_image.scanLine(0), y);
3059 		}
3060 		TIFFClose(tif);
3061 	}
3062 	m_Doc->loadPict(imgName, ite);
3063 	if (ite->imageIsAvailable)
3064 		ite->setImageXYScale(ite->width() / ite->pixm.width(), ite->height() / ite->pixm.height());
3065 	if (importerFlags & LoadSavePlugin::lfCreateDoc)
3066 		ite->setLocked(itemLocked);
3067 	if (patternMode)
3068 		PatternElements.append(ite);
3069 	else
3070 		Elements.append(ite);
3071 	if (groupStack.count() != 0)
3072 		groupStack.top().append(ite);
3073 }
3074 
processComment(QDataStream & ts,const QString & comment)3075 void AIPlug::processComment(QDataStream &ts, const QString& comment)
3076 {
3077 	QString tmp = removeAIPrefix(comment);
3078 	if (tmp.startsWith("Begin_NonPrinting"))
3079 	{
3080 		while (!ts.atEnd())
3081 		{
3082 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3083 			if (tmp.startsWith("BeginGradient"))
3084 			{
3085 				while (!ts.atEnd())
3086 				{
3087 					tmp = removeAIPrefix(readLineFromDataStream(ts));
3088 					if (tmp.startsWith("EndGradient"))
3089 						break;
3090 					processGradientData(tmp);
3091 				}
3092 			}
3093 			if (tmp.startsWith("BeginPattern:"))
3094 				processPattern(ts);
3095 			if (tmp == "BeginSymbol")
3096 				processSymbol(ts, true);
3097 			if (tmp == "BeginBrushPattern")
3098 				processSymbol(ts, false);
3099 			if (tmp.startsWith("End_NonPrinting"))
3100 				break;
3101 			if (progressDialog)
3102 			{
3103 				progressDialog->setProgress("GI", ts.device()->pos());
3104 				qApp->processEvents();
3105 			}
3106 		}
3107 	}
3108 	else if (tmp.startsWith("BeginPattern:"))
3109 		processPattern(ts);
3110 	else if (tmp.startsWith("BeginGradient"))
3111 	{
3112 		while (!ts.atEnd())
3113 		{
3114 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3115 			if (tmp.startsWith("EndGradient"))
3116 				break;
3117 			processGradientData(tmp);
3118 			if (progressDialog)
3119 			{
3120 				progressDialog->setProgress("GI", ts.device()->pos());
3121 				qApp->processEvents();
3122 			}
3123 		}
3124 	}
3125 	else if (tmp.startsWith("BeginPalette"))
3126 	{
3127 		while (!ts.atEnd())
3128 		{
3129 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3130 			if (tmp.startsWith("EndPalette"))
3131 				break;
3132 			if (progressDialog)
3133 			{
3134 				progressDialog->setProgress("GI", ts.device()->pos());
3135 				qApp->processEvents();
3136 			}
3137 		}
3138 	}
3139 	else if (tmp == "BeginSymbol")
3140 		processSymbol(ts, true);
3141 	else if (tmp == "BeginBrushPattern")
3142 		processSymbol(ts, false);
3143 /*	{
3144 		while (!ts.atEnd())
3145 		{
3146 			processSymbol(ts);
3147 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3148 			if (tmp.startsWith("EndSymbol"))
3149 				break;
3150 			if (progressDialog)
3151 			{
3152 				progressDialog->setProgress("GI", ts.device()->pos());
3153 				qApp->processEvents();
3154 			}
3155 		}
3156 	} */
3157 	else if (tmp.startsWith("BeginDocumentData"))
3158 	{
3159 		while (!ts.atEnd())
3160 		{
3161 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3162 			if (tmp.startsWith("EndDocumentData"))
3163 				break;
3164 			if (progressDialog)
3165 			{
3166 				progressDialog->setProgress("GI", ts.device()->pos());
3167 				qApp->processEvents();
3168 			}
3169 		}
3170 	}
3171 	else if (tmp.startsWith("BeginTextDocument"))
3172 	{
3173 		tmp = removeAIPrefix(readLineFromDataStream(ts));
3174 		while (!ts.atEnd())
3175 		{
3176 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3177 			if (tmp.startsWith("EndTextDocument"))
3178 			{
3179 			//	QByteArray fData;
3180 			//	decodeA85(fData, dataStringT);
3181 				break;
3182 			}
3183 		//	else
3184 		//		dataStringT += tmp.mid(1);
3185 			if (progressDialog)
3186 			{
3187 				progressDialog->setProgress("GI", ts.device()->pos());
3188 				qApp->processEvents();
3189 			}
3190 		}
3191 	}
3192 	else if (tmp.startsWith("%%BeginProlog"))
3193 	{
3194 		while (!ts.atEnd())
3195 		{
3196 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3197 			if (tmp.startsWith("%%EndProlog"))
3198 				break;
3199 			if (progressDialog)
3200 			{
3201 				progressDialog->setProgress("GI", ts.device()->pos());
3202 				qApp->processEvents();
3203 			}
3204 		}
3205 	}
3206 	else if (tmp.startsWith("%%BeginData"))
3207 	{
3208 		while (!ts.atEnd())
3209 		{
3210 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3211 			if (tmp.startsWith("%%EndData"))
3212 				break;
3213 			if (progressDialog)
3214 			{
3215 				progressDialog->setProgress("GI", ts.device()->pos());
3216 				qApp->processEvents();
3217 			}
3218 		}
3219 	}
3220 	else if (tmp.startsWith("%%BeginCrops"))
3221 	{
3222 		while (!ts.atEnd())
3223 		{
3224 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3225 			if (tmp.startsWith("%%EndCrops"))
3226 				break;
3227 			if (progressDialog)
3228 			{
3229 				progressDialog->setProgress("GI", ts.device()->pos());
3230 				qApp->processEvents();
3231 			}
3232 		}
3233 	}
3234 	else if (tmp.startsWith("BeginRaster"))
3235 	{
3236 		processRaster(ts);
3237 		if (progressDialog)
3238 		{
3239 			progressDialog->setProgress("GI", ts.device()->pos());
3240 			qApp->processEvents();
3241 		}
3242 	}
3243 	else if (tmp.contains("BeginRaster") && (tmp.startsWith("%")))
3244 	{
3245 		while (!ts.atEnd())
3246 		{
3247 			tmp = readLineFromDataStream(ts);
3248 			if (tmp.contains("EndRaster"))
3249 				break;
3250 			if (progressDialog)
3251 			{
3252 				progressDialog->setProgress("GI", ts.device()->pos());
3253 				qApp->processEvents();
3254 			}
3255 		}
3256 	}
3257 	else if (tmp.startsWith("BeginSVGFilter"))
3258 	{
3259 		while (!ts.atEnd())
3260 		{
3261 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3262 			if (tmp.startsWith("EndSVGFilter"))
3263 				break;
3264 			if (progressDialog)
3265 			{
3266 				progressDialog->setProgress("GI", ts.device()->pos());
3267 				qApp->processEvents();
3268 			}
3269 		}
3270 	}
3271 	else if (tmp.startsWith("BeginArtStyles"))
3272 	{
3273 		while (!ts.atEnd())
3274 		{
3275 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3276 			if (tmp.startsWith("EndArtStyles"))
3277 				break;
3278 			if (progressDialog)
3279 			{
3280 				progressDialog->setProgress("GI", ts.device()->pos());
3281 				qApp->processEvents();
3282 			}
3283 		}
3284 	}
3285 	else if (tmp.startsWith("BeginPluginObject"))
3286 	{
3287 		while (!ts.atEnd())
3288 		{
3289 			tmp = removeAIPrefix(readLineFromDataStream(ts));
3290 			if (tmp.startsWith("EndPluginObject"))
3291 				break;
3292 			if (progressDialog)
3293 			{
3294 				progressDialog->setProgress("GI", ts.device()->pos());
3295 				qApp->processEvents();
3296 			}
3297 		}
3298 	}
3299 	else if (tmp.startsWith("BeginLayer"))
3300 	{
3301 		while (!ts.atEnd())
3302 		{
3303 			QString rl = readLineFromDataStream(ts);
3304 			tmp = removeAIPrefix(rl);
3305 			if (tmp.startsWith("BeginRaster"))
3306 			{
3307 				processRaster(ts);
3308 				continue;
3309 			}
3310 			if (tmp.startsWith("EndLayer"))
3311 				break;
3312 			processData(rl);
3313 			if (progressDialog)
3314 			{
3315 				progressDialog->setProgress("GI", ts.device()->pos());
3316 				qApp->processEvents();
3317 			}
3318 		}
3319 	}
3320 }
3321 
convert(const QString & fn)3322 bool AIPlug::convert(const QString& fn)
3323 {
3324 	QString tmp;
3325 	LineW = 1.0;
3326 	Opacity = 1.0;
3327 	blendMode = 0;
3328 	CurrColorFill = "White";
3329 	CurrFillShade = 100.0;
3330 	CurrColorStroke = "Black";
3331 	CurrStrokeShade = 100.0;
3332 	JoinStyle = Qt::MiterJoin;
3333 	CapStyle = Qt::FlatCap;
3334 	DashPattern.clear();
3335 	DashOffset = 0.0;
3336 	fillRule = false;
3337 	FirstU = false;
3338 	WasU = false;
3339 	firstLayer = true;
3340 	patternMode = false;
3341 	symbolMode = false;
3342 	meshMode = false;
3343 	dataMode = false;
3344 	fObjectMode = false;
3345 	dataString.clear();
3346 	itemLocked = false;
3347 	patternX1 = 0.0;
3348 	patternY1 = 0.0;
3349 	patternX2 = 0.0;
3350 	patternY2 = 0.0;
3351 	Coords.resize(0);
3352 	Coords.svgInit();
3353 	clipCoords.resize(0);
3354 	clipCoords.svgInit();
3355 	currentSpecialPath.resize(0);
3356 	currentSpecialPath.svgInit();
3357 	currentPoint = FPoint(0.0, 0.0);
3358 	currentLayer = 0;
3359 	currentGradient = VGradient(VGradient::linear);
3360 	currentGradient.clearStops();
3361 	currentGradient.setRepeatMethod( VGradient::none );
3362 	currentGradientName = "";
3363 	currentGradientMatrix = QTransform();
3364 	currentGradientOrigin = QPointF(0.0, 0.0);
3365 	currentGradientAngle = 0.0;
3366 	currentGradientLength = 1.0;
3367 	currentPatternName.clear();
3368 	currentPatternX = 0.0;
3369 	currentPatternY = 0.0;
3370 	currentPatternXScale = 1.0;
3371 	currentPatternYScale = 1.0;
3372 	currentPatternRotation = 0.0;
3373 	currentStrokePatternName = "";
3374 	currentStrokePatternX = 0.0;
3375 	currentStrokePatternY = 0.0;
3376 	currentStrokePatternXScale = 1.0;
3377 	currentStrokePatternYScale = 1.0;
3378 	currentStrokePatternRotation = 0.0;
3379 	QList<PageItem*> gElements;
3380 	groupStack.push(gElements);
3381 	clipStack.push(clipCoords);
3382 	commandList << "m" << "l" << "L" << "c" << "C" << "v" << "V" << "y" << "Y";	// Path construction
3383 	commandList << "b" << "B" << "f" << "F" << "s" << "S" << "*u" << "*U";		// Object creation
3384 	commandList << "u" << "U" << "W" << "q" << "Q";					// Object creation
3385 	commandList << "A" << "w" << "j" << "J" << "Xy" << "XR";			// Graphic state
3386 	commandList << "k" << "K" << "Xa" << "XA" << "x" << "X" << "XX" << "Xx";	// Color commands
3387 	commandList << "Xk" << "g" << "G" << "p" << "P";				// Color commands
3388 	commandList << "Ln" << "Lb" << "LB";						// Layer commands
3389 	commandList << "Bd" << "BD" << "%_Bs" << "Bg" << "Bb" << "BB" << "Bm" << "Xm";	// Gradient commands
3390 	commandList << "To" << "TO" << "Tf" << "Tp" << "Tx" << "TX" << "T*" << "Tk";	// Text commands
3391 	commandList << "Tc" << "Tz";							// Text commands
3392 	commandList << "XI" << "XG" << "Xh";						// Image commands
3393 	commandList << "n" << "N" << "*" << "[";					// Special commands
3394 	commandList << "X!" << "X#";							// Mesh commands
3395 	commandList << "M" << "d" << "D" << "E";					// unimplemented
3396 	commandList << "h" << "H" << "i" << "I" << "Np" << "O";				// unimplemented
3397 	commandList << "P" << "R";							// unimplemented
3398 	commandList << "XI" << "XF" << "XG" << "XT" << "Z" << "`" << "~" << "_" << "@";	// unimplemented
3399 	commandList << "&" << "*w" << "*W" << "Ap" << "Ar";				// unimplemented
3400 	if (progressDialog)
3401 	{
3402 		progressDialog->setOverallProgress(2);
3403 		progressDialog->setLabel("GI", tr("Generating Items"));
3404 		qApp->processEvents();
3405 	}
3406 	QFile f(fn);
3407 	if (f.open(QIODevice::ReadOnly))
3408 	{
3409 		int fSize = (int) f.size();
3410 		if (progressDialog)
3411 		{
3412 			progressDialog->setTotalSteps("GI", fSize);
3413 			qApp->processEvents();
3414 		}
3415 		QDataStream ts(&f);
3416 		while (!ts.atEnd())
3417 		{
3418 			tmp = readLineFromDataStream(ts);
3419 			if (tmp.startsWith("%"))
3420 				processComment(ts, tmp);
3421 			else
3422 				processData(tmp);
3423 			if (progressDialog)
3424 			{
3425 				progressDialog->setProgress("GI", ts.device()->pos());
3426 				qApp->processEvents();
3427 			}
3428 		}
3429 		f.close();
3430 	}
3431 	if (progressDialog)
3432 		progressDialog->close();
3433 	return true;
3434 }
3435