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 <algorithm>
9
10 #include <QByteArray>
11 #include <QCursor>
12 #include <QDrag>
13 #include <QFile>
14 #include <QList>
15 #include <QMimeData>
16 #include <QRegExp>
17 #include <QStack>
18 #include <QDebug>
19
20 #include <cstdlib>
21
22 #include "importxfig.h"
23
24 #include "commonstrings.h"
25 #include "loadsaveplugin.h"
26 #include "pageitem.h"
27 #include "pagesize.h"
28 #include "prefscontext.h"
29 #include "prefsfile.h"
30 #include "prefsmanager.h"
31 #include "prefstable.h"
32 #include "rawimage.h"
33 #include "scclocale.h"
34 #include "sccolorengine.h"
35 #include "scconfig.h"
36 #include "scmimedata.h"
37 #include "scpaths.h"
38 #include "scpattern.h"
39 #include "scribusXml.h"
40 #include "scribuscore.h"
41 #include "scribusdoc.h"
42 #include "scribusview.h"
43 #include "sctextstream.h"
44 #include "selection.h"
45 #include "ui/customfdialog.h"
46 #include "ui/missing.h"
47 #include "ui/multiprogressdialog.h"
48 #include "ui/propertiespalette.h"
49 #include "undomanager.h"
50 #include "util.h"
51 #include "util_formats.h"
52 #include "util_math.h"
53
XfigPlug(ScribusDoc * doc,int flags)54 XfigPlug::XfigPlug(ScribusDoc* doc, int flags)
55 {
56 tmpSel=new Selection(this, false);
57 m_Doc=doc;
58 importerFlags = flags;
59 interactive = (flags & LoadSavePlugin::lfInteractive);
60 progressDialog = nullptr;
61 }
62
readThumbnail(const QString & fName)63 QImage XfigPlug::readThumbnail(const QString& fName)
64 {
65 QFileInfo fi = QFileInfo(fName);
66 baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
67 double w=0.0, h=0.0, x=0.0, y=0.0;
68 parseHeader(fName, x, y, w, h);
69 docX = x;
70 docY = y;
71 if (w == 0.0)
72 w = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
73 if (h == 0.0)
74 h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
75 docWidth = w - x;
76 docHeight = h - y;
77 progressDialog = nullptr;
78 m_Doc = new ScribusDoc();
79 m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
80 m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
81 m_Doc->addPage(0);
82 m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
83 baseX = m_Doc->currentPage()->xOffset();
84 baseY = m_Doc->currentPage()->yOffset();
85 Elements.clear();
86 CustColors.clear();
87 importedColors.insert(0, "Black");
88 importedColors.insert(1, "Blue");
89 importedColors.insert(2, "Green");
90 importedColors.insert(3, "Cyan");
91 importedColors.insert(4, "Red");
92 importedColors.insert(5, "Magenta");
93 importedColors.insert(6, "Yellow");
94 importedColors.insert(7, "White");
95 importedColors.insert(8, "Blue4");
96 importedColors.insert(9, "Blue3");
97 importedColors.insert(10, "Blue2");
98 importedColors.insert(11, "LtBlue");
99 importedColors.insert(12, "Green4");
100 importedColors.insert(13, "Green3");
101 importedColors.insert(14, "Green2");
102 importedColors.insert(15, "Cyan4");
103 importedColors.insert(16, "Cyan3");
104 importedColors.insert(17, "Cyan2");
105 importedColors.insert(18, "Red4");
106 importedColors.insert(19, "Red3");
107 importedColors.insert(20, "Red2");
108 importedColors.insert(21, "Magenta4");
109 importedColors.insert(22, "Magenta3");
110 importedColors.insert(23, "Magenta2");
111 importedColors.insert(24, "Brown4");
112 importedColors.insert(25, "Brown3");
113 importedColors.insert(26, "Brown2");
114 importedColors.insert(27, "Pink4");
115 importedColors.insert(28, "Pink3");
116 importedColors.insert(29, "Pink2");
117 importedColors.insert(30, "Pink");
118 importedColors.insert(31, "Gold");
119 CustColors.insert("Blue", ScColor(0, 0, 255));
120 CustColors.insert("Blue4", ScColor(0, 0, 144));
121 CustColors.insert("Blue3", ScColor(0, 0, 176));
122 CustColors.insert("Blue2", ScColor(0, 0, 208));
123 CustColors.insert("LtBlue", ScColor(135, 206, 255));
124 CustColors.insert("Cyan", ScColor(255, 0, 0, 0));
125 CustColors.insert("Cyan4", ScColor(0, 144, 144));
126 CustColors.insert("Cyan3", ScColor(0, 176, 176));
127 CustColors.insert("Cyan2", ScColor(0, 208, 208));
128 CustColors.insert("Green", ScColor(255, 0, 255, 0));
129 CustColors.insert("Green4", ScColor(0, 144, 0));
130 CustColors.insert("Green3", ScColor(0, 176, 0));
131 CustColors.insert("Green2", ScColor(0, 208, 0));
132 CustColors.insert("Red", ScColor(0, 255, 255, 0));
133 CustColors.insert("Red4", ScColor(144, 0, 0));
134 CustColors.insert("Red3", ScColor(176, 0, 0));
135 CustColors.insert("Red2", ScColor(208, 0, 0));
136 CustColors.insert("Yellow", ScColor(0, 0, 255, 0));
137 CustColors.insert("Magenta", ScColor(0, 255, 0, 0));
138 CustColors.insert("Magenta4", ScColor(144, 0, 144));
139 CustColors.insert("Magenta3", ScColor(176, 0, 176));
140 CustColors.insert("Magenta2", ScColor(208, 0, 208));
141 CustColors.insert("Brown4", ScColor(128, 48, 0));
142 CustColors.insert("Brown3", ScColor(160, 64, 0));
143 CustColors.insert("Brown2", ScColor(192, 96, 0));
144 CustColors.insert("Pink4", ScColor(255, 128, 128));
145 CustColors.insert("Pink3", ScColor(255, 160, 160));
146 CustColors.insert("Pink2", ScColor(255, 192, 192));
147 CustColors.insert("Pink", ScColor(255, 224, 224));
148 CustColors.insert("Gold", ScColor(255, 215, 0));
149 m_Doc->setLoading(true);
150 m_Doc->DoDrawing = false;
151 m_Doc->scMW()->setScriptRunning(true);
152 QString CurDirP = QDir::currentPath();
153 QDir::setCurrent(fi.path());
154 if (convert(fName))
155 {
156 tmpSel->clear();
157 QDir::setCurrent(CurDirP);
158 if (Elements.count() > 1)
159 m_Doc->groupObjectsList(Elements);
160 m_Doc->DoDrawing = true;
161 m_Doc->m_Selection->delaySignalsOn();
162 QImage tmpImage;
163 if (Elements.count() > 0)
164 {
165 for (int dre=0; dre<Elements.count(); ++dre)
166 {
167 tmpSel->addItem(Elements.at(dre), true);
168 }
169 tmpSel->setGroupRect();
170 double xs = tmpSel->width();
171 double ys = tmpSel->height();
172 tmpImage = Elements.at(0)->DrawObj_toImage(500);
173 tmpImage.setText("XSize", QString("%1").arg(xs));
174 tmpImage.setText("YSize", QString("%1").arg(ys));
175 }
176 m_Doc->scMW()->setScriptRunning(false);
177 m_Doc->setLoading(false);
178 m_Doc->m_Selection->delaySignalsOff();
179 delete m_Doc;
180 return tmpImage;
181 }
182 QDir::setCurrent(CurDirP);
183 m_Doc->DoDrawing = true;
184 m_Doc->scMW()->setScriptRunning(false);
185 delete m_Doc;
186 return QImage();
187 }
188
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)189 bool XfigPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
190 {
191 bool success = false;
192 interactive = (flags & LoadSavePlugin::lfInteractive);
193 importerFlags = flags;
194 cancel = false;
195 double x, y, b, h;
196 bool ret = false;
197 CustColors.clear();
198 importedColors.insert(0, "Black");
199 importedColors.insert(1, "Blue");
200 importedColors.insert(2, "Green");
201 importedColors.insert(3, "Cyan");
202 importedColors.insert(4, "Red");
203 importedColors.insert(5, "Magenta");
204 importedColors.insert(6, "Yellow");
205 importedColors.insert(7, "White");
206 importedColors.insert(8, "Blue4");
207 importedColors.insert(9, "Blue3");
208 importedColors.insert(10, "Blue2");
209 importedColors.insert(11, "LtBlue");
210 importedColors.insert(12, "Green4");
211 importedColors.insert(13, "Green3");
212 importedColors.insert(14, "Green2");
213 importedColors.insert(15, "Cyan4");
214 importedColors.insert(16, "Cyan3");
215 importedColors.insert(17, "Cyan2");
216 importedColors.insert(18, "Red4");
217 importedColors.insert(19, "Red3");
218 importedColors.insert(20, "Red2");
219 importedColors.insert(21, "Magenta4");
220 importedColors.insert(22, "Magenta3");
221 importedColors.insert(23, "Magenta2");
222 importedColors.insert(24, "Brown4");
223 importedColors.insert(25, "Brown3");
224 importedColors.insert(26, "Brown2");
225 importedColors.insert(27, "Pink4");
226 importedColors.insert(28, "Pink3");
227 importedColors.insert(29, "Pink2");
228 importedColors.insert(30, "Pink");
229 importedColors.insert(31, "Gold");
230 CustColors.insert("Blue", ScColor(0, 0, 255));
231 CustColors.insert("Blue4", ScColor(0, 0, 144));
232 CustColors.insert("Blue3", ScColor(0, 0, 176));
233 CustColors.insert("Blue2", ScColor(0, 0, 208));
234 CustColors.insert("LtBlue", ScColor(135, 206, 255));
235 CustColors.insert("Cyan", ScColor(255, 0, 0, 0));
236 CustColors.insert("Cyan4", ScColor(0, 144, 144));
237 CustColors.insert("Cyan3", ScColor(0, 176, 176));
238 CustColors.insert("Cyan2", ScColor(0, 208, 208));
239 CustColors.insert("Green", ScColor(255, 0, 255, 0));
240 CustColors.insert("Green4", ScColor(0, 144, 0));
241 CustColors.insert("Green3", ScColor(0, 176, 0));
242 CustColors.insert("Green2", ScColor(0, 208, 0));
243 CustColors.insert("Red", ScColor(0, 255, 255, 0));
244 CustColors.insert("Red4", ScColor(144, 0, 0));
245 CustColors.insert("Red3", ScColor(176, 0, 0));
246 CustColors.insert("Red2", ScColor(208, 0, 0));
247 CustColors.insert("Yellow", ScColor(0, 0, 255, 0));
248 CustColors.insert("Magenta", ScColor(0, 255, 0, 0));
249 CustColors.insert("Magenta4", ScColor(144, 0, 144));
250 CustColors.insert("Magenta3", ScColor(176, 0, 176));
251 CustColors.insert("Magenta2", ScColor(208, 0, 208));
252 CustColors.insert("Brown4", ScColor(128, 48, 0));
253 CustColors.insert("Brown3", ScColor(160, 64, 0));
254 CustColors.insert("Brown2", ScColor(192, 96, 0));
255 CustColors.insert("Pink4", ScColor(255, 128, 128));
256 CustColors.insert("Pink3", ScColor(255, 160, 160));
257 CustColors.insert("Pink2", ScColor(255, 192, 192));
258 CustColors.insert("Pink", ScColor(255, 224, 224));
259 CustColors.insert("Gold", ScColor(255, 215, 0));
260 QFileInfo fi = QFileInfo(fNameIn);
261 if ( !ScCore->usingGUI() )
262 {
263 interactive = false;
264 showProgress = false;
265 }
266 baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
267 if ( showProgress )
268 {
269 ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
270 progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
271 QStringList barNames, barTexts;
272 barNames << "GI";
273 barTexts << tr("Analyzing File:");
274 QList<bool> barsNumeric;
275 barsNumeric << false;
276 progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
277 progressDialog->setOverallTotalSteps(3);
278 progressDialog->setOverallProgress(0);
279 progressDialog->setProgress("GI", 0);
280 progressDialog->show();
281 connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
282 qApp->processEvents();
283 }
284 else
285 progressDialog = nullptr;
286 /* Set default Page to size defined in Preferences */
287 x = 0.0;
288 y = 0.0;
289 b = 0.0;
290 h = 0.0;
291 if (progressDialog)
292 {
293 progressDialog->setOverallProgress(1);
294 qApp->processEvents();
295 }
296 parseHeader(fNameIn, x, y, b, h);
297 docX = x;
298 docY = y;
299 if (b == 0.0)
300 b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
301 if (h == 0.0)
302 h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
303 docWidth = b - x;
304 docHeight = h - y;
305 baseX = 0;
306 baseY = 0;
307 if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
308 {
309 m_Doc->setPage(b-x, h-y, 0, 0, 0, 0, 0, 0, false, false);
310 m_Doc->addPage(0);
311 m_Doc->view()->addPage(0, true);
312 baseX = 0;
313 baseY = 0;
314 }
315 else
316 {
317 if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
318 {
319 m_Doc=ScCore->primaryMainWindow()->doFileNew(b-x, h-y, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
320 ScCore->primaryMainWindow()->HaveNewDoc();
321 ret = true;
322 baseX = 0;
323 baseY = 0;
324 }
325 }
326 if (flags & LoadSavePlugin::lfCreateDoc)
327 {
328 m_Doc->documentInfo().setAuthor(docCreator);
329 m_Doc->documentInfo().setPublisher(docOrganisation);
330 m_Doc->documentInfo().setTitle(docTitle);
331 m_Doc->documentInfo().setDate(docDate+" "+docTime);
332 }
333 if ((!ret) && (interactive))
334 {
335 baseX = m_Doc->currentPage()->xOffset();
336 baseY = m_Doc->currentPage()->yOffset();
337 }
338 if ((ret) || (!interactive))
339 {
340 if (b-x > h-y)
341 m_Doc->setPageOrientation(1);
342 else
343 m_Doc->setPageOrientation(0);
344 m_Doc->setPageSize("Custom");
345 }
346 if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
347 m_Doc->view()->deselectItems();
348 Elements.clear();
349 m_Doc->setLoading(true);
350 m_Doc->DoDrawing = false;
351 if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
352 m_Doc->view()->updatesOn(false);
353 m_Doc->scMW()->setScriptRunning(true);
354 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
355 QString CurDirP = QDir::currentPath();
356 QDir::setCurrent(fi.path());
357 if (convert(fNameIn))
358 {
359 tmpSel->clear();
360 QDir::setCurrent(CurDirP);
361 if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
362 m_Doc->groupObjectsList(Elements);
363 m_Doc->DoDrawing = true;
364 m_Doc->scMW()->setScriptRunning(false);
365 m_Doc->setLoading(false);
366 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
367 if ((Elements.count() > 0) && (!ret) && (interactive))
368 {
369 if (flags & LoadSavePlugin::lfScripted)
370 {
371 bool loadF = m_Doc->isLoading();
372 m_Doc->setLoading(false);
373 m_Doc->changed();
374 m_Doc->setLoading(loadF);
375 if (!(flags & LoadSavePlugin::lfLoadAsPattern))
376 {
377 m_Doc->m_Selection->delaySignalsOn();
378 for (int dre=0; dre<Elements.count(); ++dre)
379 {
380 m_Doc->m_Selection->addItem(Elements.at(dre), true);
381 }
382 m_Doc->m_Selection->delaySignalsOff();
383 m_Doc->m_Selection->setGroupRect();
384 if (m_Doc->view() != nullptr)
385 m_Doc->view()->updatesOn(true);
386 }
387 }
388 else
389 {
390 m_Doc->DragP = true;
391 m_Doc->DraggedElem = nullptr;
392 m_Doc->DragElements.clear();
393 m_Doc->m_Selection->delaySignalsOn();
394 for (int dre=0; dre<Elements.count(); ++dre)
395 {
396 tmpSel->addItem(Elements.at(dre), true);
397 }
398 tmpSel->setGroupRect();
399 ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
400 m_Doc->itemSelection_DeleteItem(tmpSel);
401 m_Doc->view()->updatesOn(true);
402 m_Doc->m_Selection->delaySignalsOff();
403 // We must copy the TransationSettings object as it is owned
404 // by handleObjectImport method afterwards
405 TransactionSettings* transacSettings = new TransactionSettings(trSettings);
406 m_Doc->view()->handleObjectImport(md, transacSettings);
407 m_Doc->DragP = false;
408 m_Doc->DraggedElem = nullptr;
409 m_Doc->DragElements.clear();
410 }
411 }
412 else
413 {
414 m_Doc->changed();
415 m_Doc->reformPages();
416 if (!(flags & LoadSavePlugin::lfLoadAsPattern))
417 m_Doc->view()->updatesOn(true);
418 }
419 success = true;
420 }
421 else
422 {
423 QDir::setCurrent(CurDirP);
424 m_Doc->DoDrawing = true;
425 m_Doc->scMW()->setScriptRunning(false);
426 m_Doc->view()->updatesOn(true);
427 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
428 }
429 if (interactive)
430 m_Doc->setLoading(false);
431 //CB If we have a gui we must refresh it if we have used the progressbar
432 if (!(flags & LoadSavePlugin::lfLoadAsPattern))
433 {
434 if ((showProgress) && (!interactive))
435 m_Doc->view()->DrawNew();
436 }
437 qApp->restoreOverrideCursor();
438 return success;
439 }
440
~XfigPlug()441 XfigPlug::~XfigPlug()
442 {
443 delete progressDialog;
444 delete tmpSel;
445 }
446
parseHeader(const QString & fName,double & x,double & y,double & b,double & h)447 bool XfigPlug::parseHeader(const QString& fName, double &x, double &y, double &b, double &h)
448 {
449 bool found = false;
450 QFile f(fName);
451 if (f.open(QIODevice::ReadOnly))
452 {
453 QDataStream ts(&f);
454 QString version = readLineFromDataStream(ts);
455 if (!version.startsWith("#FIG 3"))
456 {
457 f.close();
458 return false;
459 }
460 QString orientation = readLineFromDataStream(ts);
461 QString justification = readLineFromDataStream(ts);
462 QString units = readLineFromDataStream(ts);
463 QString papersize = readLineFromDataStream(ts);
464 PageSize ps(papersize);
465 if (orientation.startsWith("Landscape"))
466 {
467 h = ps.width();
468 b = ps.height();
469 }
470 else
471 {
472 b = ps.width();
473 h = ps.height();
474 }
475 f.close();
476 found = true;
477 }
478 return found;
479 }
480
parseColor(QString data)481 void XfigPlug::parseColor(QString data)
482 {
483 if (data.isEmpty())
484 return;
485 int colorNum, dummy;
486 QString colorValues;
487 ScColor tmp;
488 ScTextStream Code(&data, QIODevice::ReadOnly);
489 Code >> dummy >> colorNum >> colorValues;
490 tmp.setNamedColor(colorValues);
491 tmp.setSpotColor(false);
492 tmp.setRegistrationColor(false);
493 QString namPrefix = "FromXfig%1-"+colorValues;
494 CustColors.insert(namPrefix.arg(colorNum), tmp);
495 importedColors.insert(colorNum, namPrefix.arg(colorNum));
496 }
497
useColor(int colorNum,int area_fill,bool forFill)498 void XfigPlug::useColor(int colorNum, int area_fill, bool forFill)
499 {
500 QString color = CommonStrings::None;
501 int shade = 100;
502 if (forFill)
503 {
504 if (area_fill == -1)
505 color = CommonStrings::None;
506 else
507 {
508 if ((colorNum == -1) || (colorNum == 0))
509 {
510 if (area_fill == 0)
511 {
512 color = "White";
513 shade = 100;
514 }
515 else if (area_fill == 20)
516 {
517 color = "Black";
518 shade = 100;
519 }
520 else if ((area_fill > 0) && (area_fill < 20))
521 {
522 color = "Black";
523 shade = qRound(100.0 / 19.0 * area_fill);
524 }
525 }
526 else if (colorNum == 7)
527 {
528 if (area_fill == 0)
529 {
530 color = "Black";
531 shade = 100;
532 }
533 else if (area_fill == 20)
534 {
535 color = "White";
536 shade = 100;
537 }
538 else if ((area_fill > 0) && (area_fill < 20))
539 {
540 color = "Black";
541 shade = qRound(100.0 / 19.0 * (20 - area_fill));
542 }
543 }
544 else
545 {
546 if (importedColors.contains(colorNum))
547 {
548 color = importedColors[colorNum];
549 if (!m_Doc->PageColors.contains(color))
550 m_Doc->PageColors.insert(color, CustColors[color]);
551 int sat = area_fill - 20;
552 if ((sat > 0) && (sat < 20))
553 shade = qRound(100.0 / 19.0 * sat);
554 }
555 else
556 color = CommonStrings::None;
557 }
558 }
559 CurrColorFill = color;
560 CurrFillShade = shade;
561 }
562 else
563 {
564 if (area_fill == -1)
565 CurrColorStroke = CommonStrings::None;
566 else
567 {
568 if ((colorNum == -1) || (colorNum == 0))
569 CurrColorStroke = "Black";
570 else
571 {
572 if (importedColors.contains(colorNum))
573 {
574 CurrColorStroke = importedColors[colorNum];
575 if (!m_Doc->PageColors.contains(CurrColorStroke))
576 m_Doc->PageColors.insert(CurrColorStroke, CustColors[CurrColorStroke]);
577 }
578 else
579 CurrColorStroke = CommonStrings::None;
580 }
581 }
582 }
583 }
584
getDashValues(double linewidth,int code)585 QVector<double> XfigPlug::getDashValues(double linewidth, int code)
586 {
587 QVector<double> tmp;
588 if (code == 1)
589 {
590 tmp << qMax(4.0 * linewidth, 0.1);
591 tmp << qMax(2.0 * linewidth, 0.1);
592 }
593 else if (code == 2)
594 {
595 tmp << qMax(1.0 * linewidth, 0.1);
596 tmp << qMax(2.0 * linewidth, 0.1);
597 }
598 else if (code == 3)
599 {
600 tmp << qMax(4.0 * linewidth, 0.1);
601 tmp << qMax(2.0 * linewidth, 0.1);
602 tmp << qMax(1.0 * linewidth, 0.1);
603 tmp << qMax(2.0 * linewidth, 0.1);
604 }
605 else if (code == 4)
606 {
607 tmp << qMax(4.0 * linewidth, 0.1);
608 tmp << qMax(2.0 * linewidth, 0.1);
609 tmp << qMax(1.0 * linewidth, 0.1);
610 tmp << qMax(2.0 * linewidth, 0.1);
611 tmp << qMax(1.0 * linewidth, 0.1);
612 tmp << qMax(2.0 * linewidth, 0.1);
613 }
614 else if (code == 5)
615 {
616 tmp << qMax(4.0 * linewidth, 0.1);
617 tmp << qMax(2.0 * linewidth, 0.1);
618 tmp << qMax(1.0 * linewidth, 0.1);
619 tmp << qMax(2.0 * linewidth, 0.1);
620 tmp << qMax(1.0 * linewidth, 0.1);
621 tmp << qMax(2.0 * linewidth, 0.1);
622 tmp << qMax(1.0 * linewidth, 0.1);
623 tmp << qMax(2.0 * linewidth, 0.1);
624 }
625 return tmp;
626 }
627
processArrows(int forward_arrow,QString fArrowData,int backward_arrow,QString bArrowData,int depth,PageItem * ite)628 void XfigPlug::processArrows(int forward_arrow, QString fArrowData, int backward_arrow, QString bArrowData, int depth, PageItem *ite)
629 {
630 int arrow_typeAF; // (enumeration type)
631 int arrow_styleAF; // (enumeration type)
632 float arrow_thicknessAF; // (1/80 inch)
633 float arrow_widthAF; // (Fig units)
634 float arrow_heightAF; // (Fig units)
635 int arrow_typeAB; // (enumeration type)
636 int arrow_styleAB; // (enumeration type)
637 float arrow_thicknessAB; // (1/80 inch)
638 float arrow_widthAB; // (Fig units)
639 float arrow_heightAB; // (Fig units)
640 FPointArray arrow;
641 int z = -1;
642 PageItem::ItemType iteType;
643 if (forward_arrow == 1)
644 {
645 arrow.resize(0);
646 ScTextStream CodeAF(&fArrowData, QIODevice::ReadOnly);
647 CodeAF >> arrow_typeAF >> arrow_styleAF >> arrow_thicknessAF >> arrow_widthAF >> arrow_heightAF;
648 arrow_widthAF = fig2Pts(arrow_widthAF);
649 arrow_heightAF = fig2Pts(arrow_heightAF);
650 arrow_thicknessAF = arrow_thicknessAF / 80.0 * 72.0;
651 FPoint End = ite->PoLine.point(ite->PoLine.size()-2);
652 for (uint xx = ite->PoLine.size()-1; xx > 0; xx -= 2)
653 {
654 FPoint Vector = ite->PoLine.point(xx);
655 if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
656 {
657 double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
658 QTransform arrowTrans;
659 if (arrow_typeAF == 0)
660 arrow.parseSVG("M -1, -0.5 L 0, 0 L -1, 0.5");
661 else if (arrow_typeAF == 1)
662 arrow.parseSVG("M -1, -0.5 L 0, 0 L -1, 0.5 z");
663 else if (arrow_typeAF == 2)
664 arrow.parseSVG("M -1, -0.5 L 0, 0 L -1, 0.5 L -0.7 0 z");
665 else if (arrow_typeAF == 3)
666 arrow.parseSVG("M -0.7, -0.5 L 0, 0 L -0.7, 0.5 L -1 0 z");
667 arrowTrans.translate(End.x(), End.y());
668 arrowTrans.rotate(r);
669 arrowTrans.scale(arrow_heightAF, arrow_widthAF);
670 arrow.map(arrowTrans);
671 break;
672 }
673 }
674 QString fillC = "White";
675 if (arrow_styleAF == 1)
676 fillC = CurrColorStroke;
677 if (arrow_typeAF == 0)
678 {
679 fillC = CommonStrings::None;
680 iteType = PageItem::PolyLine;
681 }
682 else
683 iteType = PageItem::Polygon;
684 z = m_Doc->itemAdd(iteType, PageItem::Unspecified, ite->xPos(), ite->yPos(), 10, 10, arrow_thicknessAF, fillC, CurrColorStroke);
685 if (z >= 0)
686 {
687 PageItem *item = m_Doc->Items->at(z);
688 item->PoLine = arrow.copy();
689 item->ClipEdited = true;
690 item->FrameType = 3;
691 item->setFillShade(CurrFillShade);
692 item->setLineShade(CurrStrokeShade);
693 FPoint wh = getMaxClipF(&item->PoLine);
694 item->setWidthHeight(wh.x(),wh.y());
695 item->setTextFlowMode(PageItem::TextFlowDisabled);
696 m_Doc->adjustItemSize(item);
697 item->setWidthHeight(qMax(item->width(), 1.0), qMax(item->height(), 1.0));
698 depthMap.insert(999 - depth, currentItemNr);
699 currentItemNr++;
700 }
701 }
702 if (backward_arrow == 1)
703 {
704 arrow.resize(0);
705 ScTextStream CodeAB(&bArrowData, QIODevice::ReadOnly);
706 CodeAB >> arrow_typeAB >> arrow_styleAB >> arrow_thicknessAB >> arrow_widthAB >> arrow_heightAB;
707 arrow_widthAB = fig2Pts(arrow_widthAB);
708 arrow_heightAB = fig2Pts(arrow_heightAB);
709 arrow_thicknessAB = arrow_thicknessAB / 80.0 * 72.0;
710 FPointArray arrow;
711 FPoint Start = ite->PoLine.point(0);
712 for (int xx = 1; xx < ite->PoLine.size(); xx += 2)
713 {
714 FPoint Vector = ite->PoLine.point(xx);
715 if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
716 {
717 double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
718 QTransform arrowTrans;
719 if (arrow_typeAB == 0)
720 arrow.parseSVG("M -1, -0.5 L 0, 0 L -1, 0.5");
721 else if (arrow_typeAB == 1)
722 arrow.parseSVG("M -1, -0.5 L 0, 0 L -1, 0.5 z");
723 else if (arrow_typeAB == 2)
724 arrow.parseSVG("M -1, -0.5 L 0, 0 L -1, 0.5 L -0.7 0 z");
725 else if (arrow_typeAB == 3)
726 arrow.parseSVG("M -0.7, -0.5 L 0, 0 L -0.7, 0.5 L -1 0 z");
727 arrowTrans.translate(Start.x(), Start.y());
728 arrowTrans.rotate(r);
729 arrowTrans.scale(arrow_heightAB, arrow_widthAB);
730 arrow.map(arrowTrans);
731 break;
732 }
733 }
734 QString fillC = "White";
735 if (arrow_styleAB == 1)
736 fillC = CurrColorStroke;
737 if (arrow_typeAB == 0)
738 {
739 fillC = CommonStrings::None;
740 iteType = PageItem::PolyLine;
741 }
742 else
743 iteType = PageItem::Polygon;
744 z = m_Doc->itemAdd(iteType, PageItem::Unspecified, ite->xPos(), ite->yPos(), 10, 10, arrow_thicknessAB, fillC, CurrColorStroke);
745 if (z >= 0)
746 {
747 PageItem *item = m_Doc->Items->at(z);
748 item->PoLine = arrow.copy();
749 item->ClipEdited = true;
750 item->FrameType = 3;
751 item->setFillShade(CurrFillShade);
752 item->setLineShade(CurrStrokeShade);
753 FPoint wh = getMaxClipF(&item->PoLine);
754 item->setWidthHeight(wh.x(),wh.y());
755 item->setTextFlowMode(PageItem::TextFlowDisabled);
756 m_Doc->adjustItemSize(item);
757 item->setWidthHeight(qMax(item->width(), 1.0), qMax(item->height(), 1.0));
758 depthMap.insert(999 - depth, currentItemNr);
759 currentItemNr++;
760 }
761 }
762 }
763
processPolyline(QDataStream & ts,const QString & data)764 void XfigPlug::processPolyline(QDataStream &ts, const QString& data)
765 {
766 QString tmp = data;
767 QString fArrowData;
768 QString bArrowData;
769 int command;
770 int subtype; // (1: polyline, 2: box, 3: polygon, 4: arc-box, 5: imported-picture bounding-box)
771 int line_style; // (enumeration type)
772 int thickness; // (1/80 inch)
773 int pen_color; // (enumeration type, pen color)
774 int fill_color; // (enumeration type, fill color)
775 int depth; // (enumeration type)
776 int pen_style; // (pen style, not used)
777 int area_fill; // (enumeration type, -1 = no fill)
778 double style_val; // (1/80 inch)
779 int join_style; // (enumeration type)
780 int cap_style; // (enumeration type, only used for POLYLINE)
781 int radius; // (1/80 inch, radius of arc-boxes)
782 int forward_arrow; // (0: off, 1: on)
783 int backward_arrow; // (0: off, 1: on)
784 int npoints; // (number of points in line)
785 int pointsRead = 0;
786 int imgFlipped;
787 QString imgFile;
788 double x, y;
789 Coords.resize(0);
790 Coords.svgInit();
791 bool first = true;
792 ScTextStream Code(&tmp, QIODevice::ReadOnly);
793 Code >> command >> subtype >> line_style >> thickness >> pen_color >> fill_color >> depth >> pen_style;
794 Code >> area_fill >> style_val >> join_style >> cap_style >> radius >> forward_arrow >> backward_arrow >> npoints;
795 if (forward_arrow == 1)
796 fArrowData = readLineFromDataStream(ts);
797 if (backward_arrow == 1)
798 bArrowData = readLineFromDataStream(ts);
799 if (subtype == 5)
800 {
801 tmp = readLineFromDataStream(ts);
802 ScTextStream imf(&tmp, QIODevice::ReadOnly);
803 imf >> imgFlipped >> imgFile;
804 }
805 while (!ts.atEnd())
806 {
807 tmp = readLineFromDataStream(ts);
808 ScTextStream pts(&tmp, QIODevice::ReadOnly);
809 while (!pts.atEnd())
810 {
811 pts >> x >> y;
812 x = fig2Pts(x) - docX;
813 y = fig2Pts(y) - docY;
814 if (first)
815 {
816 Coords.svgMoveTo(x, y);
817 first = false;
818 }
819 else
820 Coords.svgLineTo(x, y);
821 pointsRead++;
822 }
823 if (pointsRead == npoints)
824 {
825 if (npoints == 1)
826 Coords.svgLineTo(x, y);
827 break;
828 }
829 }
830 useColor(pen_color, 0, false);
831 useColor(fill_color, area_fill, true);
832 LineW = thickness / 80.0 * 72.0;
833 int z = -1;
834 PageItem *ite;
835 if (subtype == 1)
836 z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
837 else if ((subtype == 2) || (subtype == 3) || (subtype == 4))
838 {
839 z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
840 Coords.svgClosePath();
841 }
842 else if (subtype == 5)
843 {
844 z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
845 Coords.svgClosePath();
846 }
847 else
848 z = -1;
849 if (z >= 0)
850 {
851 ite = m_Doc->Items->at(z);
852 ite->PoLine = Coords.copy();
853 ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
854 ite->ClipEdited = true;
855 ite->FrameType = 3;
856 ite->setFillShade(CurrFillShade);
857 ite->setLineShade(CurrStrokeShade);
858 if (line_style > 0)
859 ite->setDashes(getDashValues(LineW, line_style));
860 if (subtype == 1)
861 {
862 if (join_style == 0)
863 ite->setLineJoin(Qt::MiterJoin);
864 else if (join_style == 1)
865 ite->setLineJoin(Qt::RoundJoin);
866 else if (join_style == 2)
867 ite->setLineJoin(Qt::BevelJoin);
868 if (cap_style == 0)
869 ite->setLineEnd(Qt::FlatCap);
870 else if (cap_style == 1)
871 ite->setLineEnd(Qt::RoundCap);
872 else if (cap_style == 2)
873 ite->setLineEnd(Qt::SquareCap);
874 }
875 FPoint wh = getMaxClipF(&ite->PoLine);
876 ite->setWidthHeight(wh.x(),wh.y());
877 ite->setTextFlowMode(PageItem::TextFlowDisabled);
878 m_Doc->adjustItemSize(ite);
879 ite->setWidthHeight(qMax(ite->width(), 1.0), qMax(ite->height(), 1.0));
880 if (subtype == 4)
881 {
882 ite->setCornerRadius(radius / 80.0 * 72.0);
883 ite->FrameType = 2;
884 ite->ClipEdited = false;
885 ite->updateClip();
886 }
887 if (subtype == 5)
888 {
889 ite->Pfile = baseFile + "/" + imgFile;
890 m_Doc->loadPict(ite->Pfile, ite, false);
891 ite->setImageXYScale(72.0 / 80.0, 72.0 / 80.0);
892 ite->setImageXYOffset(0, 0);
893 }
894 depthMap.insert(999 - depth, currentItemNr);
895 currentItemNr++;
896 if ((ite->itemType() == PageItem::PolyLine) && ((forward_arrow == 1) || (backward_arrow == 1)))
897 processArrows(forward_arrow, fArrowData, backward_arrow, bArrowData, depth, ite);
898 }
899 }
900
processSpline(QDataStream & ts,const QString & data)901 void XfigPlug::processSpline(QDataStream &ts, const QString& data)
902 {
903 QString tmp = data;
904 QString fArrowData = "";
905 QString bArrowData = "";
906 int command;
907 int subtype; // 0: open approximated spline
908 // 1: closed approximated spline
909 // 2: open interpolated spline
910 // 3: closed interpolated spline
911 // 4: open x-spline
912 // 5: closed x-spline
913 int line_style; // (enumeration type)
914 int thickness; // (1/80 inch)
915 int pen_color; // (enumeration type, pen color)
916 int fill_color; // (enumeration type, fill color)
917 int depth; // (enumeration type)
918 int pen_style; // (pen style, not used)
919 int area_fill; // (enumeration type, -1 = no fill)
920 double style_val; // (1/80 inch)
921 int cap_style; // (enumeration type, only used for POLYLINE)
922 int forward_arrow; // (0: off, 1: on)
923 int backward_arrow; // (0: off, 1: on)
924 int npoints; // (number of points in line)
925 int pointsRead = 0;
926 double x, y;
927 Coords.resize(0);
928 Coords.svgInit();
929 bool first = true;
930 ScTextStream Code(&tmp, QIODevice::ReadOnly);
931 Code >> command >> subtype >> line_style >> thickness >> pen_color >> fill_color >> depth >> pen_style;
932 Code >> area_fill >> style_val >> cap_style >> forward_arrow >> backward_arrow >> npoints;
933 if (forward_arrow == 1)
934 fArrowData = readLineFromDataStream(ts);
935 if (backward_arrow == 1)
936 bArrowData = readLineFromDataStream(ts);
937 while (!ts.atEnd())
938 {
939 tmp = readLineFromDataStream(ts);
940 ScTextStream pts(&tmp, QIODevice::ReadOnly);
941 while (!pts.atEnd())
942 {
943 pts >> x >> y;
944 x = fig2Pts(x) - docX;
945 y = fig2Pts(y) - docY;
946 if (first)
947 {
948 Coords.svgMoveTo(x, y);
949 first = false;
950 }
951 else
952 Coords.svgLineTo(x, y);
953 pointsRead++;
954 }
955 if (pointsRead == npoints)
956 {
957 if (npoints == 1)
958 Coords.svgLineTo(x, y);
959 break;
960 }
961 }
962 pointsRead = 0;
963 while (!ts.atEnd())
964 {
965 tmp = readLineFromDataStream(ts);
966 ScTextStream pts(&tmp, QIODevice::ReadOnly);
967 while (!pts.atEnd())
968 {
969 pts >> x;
970 pointsRead++;
971 }
972 if (pointsRead == npoints)
973 break;
974 }
975 useColor(pen_color, 0, false);
976 useColor(fill_color, area_fill, true);
977 LineW = thickness / 80.0 * 72.0;
978 int z = -1;
979 PageItem *ite;
980 if ((subtype == 0) || (subtype == 2) || (subtype == 4))
981 z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
982 else if ((subtype == 1) || (subtype == 3) || (subtype == 5))
983 {
984 z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
985 Coords.svgClosePath();
986 }
987 if (z >= 0)
988 {
989 ite = m_Doc->Items->at(z);
990 ite->PoLine = Coords.copy();
991 ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
992 ite->ClipEdited = true;
993 ite->FrameType = 3;
994 ite->setFillShade(CurrFillShade);
995 ite->setLineShade(CurrStrokeShade);
996 if (line_style > 0)
997 ite->setDashes(getDashValues(LineW, line_style));
998 if ((subtype == 0) || (subtype == 2) || (subtype == 4))
999 {
1000 if (cap_style == 0)
1001 ite->setLineEnd(Qt::FlatCap);
1002 else if (cap_style == 1)
1003 ite->setLineEnd(Qt::RoundCap);
1004 else if (cap_style == 2)
1005 ite->setLineEnd(Qt::SquareCap);
1006 }
1007 FPoint wh = getMaxClipF(&ite->PoLine);
1008 ite->setWidthHeight(wh.x(),wh.y());
1009 ite->setTextFlowMode(PageItem::TextFlowDisabled);
1010 m_Doc->adjustItemSize(ite);
1011 ite->setWidthHeight(qMax(ite->width(), 1.0), qMax(ite->height(), 1.0));
1012 depthMap.insert(999 - depth, currentItemNr);
1013 currentItemNr++;
1014 if ((ite->itemType() == PageItem::PolyLine) && ((forward_arrow == 1) || (backward_arrow == 1)))
1015 processArrows(forward_arrow, fArrowData, backward_arrow, bArrowData, depth, ite);
1016 }
1017 }
1018
processArc(QDataStream & ts,const QString & data)1019 void XfigPlug::processArc(QDataStream &ts, const QString& data)
1020 {
1021 QString tmp = data;
1022 QString fArrowData = "";
1023 QString bArrowData = "";
1024 int command;
1025 int subtype; // (1: open ended arc, 2: pie-wedge (closed))
1026 int line_style; // (enumeration type)
1027 int thickness; // (1/80 inch)
1028 int pen_color; // (enumeration type, pen color)
1029 int fill_color; // (enumeration type, fill color)
1030 int depth; // (enumeration type)
1031 int pen_style; // (pen style, not used)
1032 int area_fill; // (enumeration type, -1 = no fill)
1033 double style_val; // (1/80 inch)
1034 int cap_style; // (enumeration type, only used for POLYLINE)
1035 int direction; // (always 1)
1036 int forward_arrow; // (0: off, 1: on)
1037 int backward_arrow; // (0: off, 1: on)
1038 double center_x, center_y; // (center of the arc)
1039 int x1, y1; // (Fig units, the 1st point the user entered)
1040 int x2, y2; // (Fig units, the 2nd point)
1041 int x3, y3; // (Fig units, the last point)
1042 ScTextStream Code(&tmp, QIODevice::ReadOnly);
1043 Code >> command >> subtype >> line_style >> thickness >> pen_color >> fill_color >> depth >> pen_style;
1044 Code >> area_fill >> style_val >> cap_style >> direction >> forward_arrow >> backward_arrow;
1045 Code >> center_x >> center_y >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
1046 if (forward_arrow == 1)
1047 fArrowData = readLineFromDataStream(ts);
1048 if (backward_arrow == 1)
1049 bArrowData = readLineFromDataStream(ts);
1050 useColor(pen_color, 0, false);
1051 useColor(fill_color, area_fill, true);
1052 LineW = thickness / 80.0 * 72.0;
1053 int z = -1;
1054 PageItem *ite;
1055 if (subtype == 1)
1056 z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
1057 else if (subtype == 2)
1058 z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColorFill, CurrColorStroke);
1059 else
1060 z = -1;
1061 center_x = fig2Pts(center_x) - docX;
1062 center_y = fig2Pts(center_y) - docY;
1063 double x1R = fig2Pts(x1) - docX;
1064 double y1R = fig2Pts(y1) - docY;
1065 double x3R = fig2Pts(x3) - docX;
1066 double y3R = fig2Pts(y3) - docY;
1067 double r1 = distance(x1R - center_x, y1R - center_y);
1068 double x0 = center_x - r1;
1069 double y0 = center_y - r1;
1070 QRectF bBox = QRectF(x0, y0, r1 * 2.0, r1 * 2.0);
1071 double angle1 = -xy2Deg(x1R - center_x, y1R - center_y);
1072 double angle2 = -xy2Deg(x3R - center_x, y3R - center_y);
1073 double sweep;
1074 if (direction == 0)
1075 {
1076 sweep = angle1 - angle2;
1077 if (sweep < 0.0)
1078 sweep = 360.0 + sweep;
1079 }
1080 else
1081 {
1082 sweep = angle2 - angle1;
1083 if (sweep < 0.0)
1084 sweep = 360.0 + sweep;
1085 double an = angle1;
1086 angle1 = angle2;
1087 angle2 = an;
1088 }
1089 QPainterPath aPath;
1090 if (subtype == 1)
1091 {
1092 aPath.arcMoveTo(bBox, angle2);
1093 aPath.arcTo(bBox, angle2, sweep);
1094 }
1095 else
1096 {
1097 aPath.moveTo(center_x, center_y);
1098 aPath.arcTo(bBox, angle2, sweep);
1099 aPath.lineTo(center_x, center_y);
1100 }
1101 FPointArray points;
1102 points.fromQPainterPath(aPath);
1103
1104 if (z >= 0)
1105 {
1106 ite = m_Doc->Items->at(z);
1107 ite->PoLine = points.copy();
1108 ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
1109 ite->ClipEdited = true;
1110 ite->FrameType = 3;
1111 ite->setFillShade(CurrFillShade);
1112 ite->setLineShade(CurrStrokeShade);
1113 if (line_style > 0)
1114 ite->setDashes(getDashValues(LineW, line_style));
1115 if (subtype == 1)
1116 {
1117 if (cap_style == 0)
1118 ite->setLineEnd(Qt::FlatCap);
1119 else if (cap_style == 1)
1120 ite->setLineEnd(Qt::RoundCap);
1121 else if (cap_style == 2)
1122 ite->setLineEnd(Qt::SquareCap);
1123 }
1124 FPoint wh = getMaxClipF(&ite->PoLine);
1125 ite->setWidthHeight(wh.x(),wh.y());
1126 ite->setTextFlowMode(PageItem::TextFlowDisabled);
1127 m_Doc->adjustItemSize(ite);
1128 ite->setWidthHeight(qMax(ite->width(), 1.0), qMax(ite->height(), 1.0));
1129 depthMap.insert(999 - depth, currentItemNr);
1130 currentItemNr++;
1131 if ((ite->itemType() == PageItem::PolyLine) && ((forward_arrow == 1) || (backward_arrow == 1)))
1132 {
1133 if (direction == 1)
1134 processArrows(forward_arrow, fArrowData, backward_arrow, bArrowData, depth, ite);
1135 else
1136 processArrows(backward_arrow, bArrowData, forward_arrow, fArrowData, depth, ite);
1137 }
1138 }
1139 }
1140
processEllipse(const QString & data)1141 void XfigPlug::processEllipse(const QString& data)
1142 {
1143 QString tmp = data;
1144 int command; // (always 1)
1145 int subtype; // (1: ellipse defined by radii
1146 // 2: ellipse defined by diameters
1147 // 3: circle defined by radius
1148 // 4: circle defined by diameter)
1149 int line_style; // (enumeration type)
1150 int thickness; // (1/80 inch)
1151 int pen_color; // (enumeration type, pen color)
1152 int fill_color; // (enumeration type, fill color)
1153 int depth; // (enumeration type)
1154 int pen_style; // (pen style, not used)
1155 int area_fill; // (enumeration type, -1 = no fill)
1156 double style_val; // (1/80 inch)
1157 int direction; // (always 1)
1158 double angle; // (radians, the angle of the x-axis)
1159 int center_x, center_y; // (Fig units)
1160 int radius_x, radius_y; // (Fig units)
1161 int start_x, start_y; // (Fig units; the 1st point entered)
1162 int end_x, end_y; // (Fig units; the last point entered)
1163 double x, y, w, h;
1164 ScTextStream Code(&tmp, QIODevice::ReadOnly);
1165 Code >> command >> subtype >> line_style >> thickness >> pen_color >> fill_color >> depth >> pen_style;
1166 Code >> area_fill >> style_val >> direction >> angle >> center_x >> center_y >> radius_x >> radius_y;
1167 Code >> start_x >> start_y >> end_x >> end_y;
1168 useColor(pen_color, 0, false);
1169 useColor(fill_color, area_fill, true);
1170 LineW = thickness / 80.0 * 72.0;
1171 w = fig2Pts(radius_x);
1172 h = fig2Pts(radius_y);
1173 x = fig2Pts(center_x) - w;
1174 y = fig2Pts(center_y) - h;
1175 w *= 2.0;
1176 h *= 2.0;
1177 x -= docX;
1178 x += m_Doc->currentPage()->xOffset();
1179 y -= docY;
1180 y += m_Doc->currentPage()->yOffset();
1181 int z = -1;
1182 PageItem *ite;
1183 z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX + x, baseY + y, w, h, LineW, CurrColorFill, CurrColorStroke);
1184 if (z >= 0)
1185 {
1186 ite = m_Doc->Items->at(z);
1187 ite->setFillShade(CurrFillShade);
1188 ite->setLineShade(CurrStrokeShade);
1189 if (line_style > 0)
1190 ite->setDashes(getDashValues(LineW, line_style));
1191 ite->setTextFlowMode(PageItem::TextFlowDisabled);
1192 int rot = m_Doc->rotationMode();
1193 m_Doc->setRotationMode ( 2);
1194 m_Doc->rotateItem(-angle * 180.0 / M_PI, ite);
1195 m_Doc->setRotationMode( rot);
1196 depthMap.insert(999 - depth, currentItemNr);
1197 currentItemNr++;
1198 }
1199 }
1200
cleanText(const QString & text)1201 QString XfigPlug::cleanText(const QString& text)
1202 {
1203 QString ret;
1204 QString tmp;
1205 bool sep = false;
1206 int sepcount = 0;
1207 for (int a = 1; a < text.count(); ++a)
1208 {
1209 QString ch = text.mid(a,1);
1210 if (sep)
1211 {
1212 if (ch == "\\")
1213 {
1214 ret += ch;
1215 sep = false;
1216 }
1217 else
1218 {
1219 tmp += ch;
1220 sepcount++;
1221 if (sepcount == 3)
1222 {
1223 sep = false;
1224 bool ok = false;
1225 if (tmp != "001")
1226 {
1227 int code = tmp.toInt(&ok, 8);
1228 if (ok)
1229 ret += QChar(code);
1230 }
1231 tmp = "";
1232 }
1233 }
1234 }
1235 else
1236 {
1237 if (ch == "\\")
1238 {
1239 sep = true;
1240 sepcount = 0;
1241 }
1242 else
1243 ret += ch;
1244 }
1245 }
1246 return ret;
1247 }
1248
processText(const QString & data)1249 void XfigPlug::processText(const QString& data)
1250 {
1251 QString tmp = data;
1252 int command; // (always 4)
1253 int subtype; // (0: Left justified
1254 // 1: Center justified
1255 // 2: Right justified)
1256 int color; // (enumeration type)
1257 int depth; // (enumeration type)
1258 int pen_style; // (enumeration , not used)
1259 int font; // (enumeration type)
1260 float font_size; // (font size in points)
1261 float angle; // (radians, the angle of the text)
1262 int font_flags; // (bit vector)
1263 float height; // (Fig units)
1264 float length; // (Fig units)
1265 int xT, yT; // (Fig units, coordinate of the origin
1266 // of the string. If sub_type = 0, it is
1267 // the lower left corner of the string.
1268 // If sub_type = 1, it is the lower
1269 // center. Otherwise it is the lower
1270 // right corner of the string.)
1271 QString text;
1272 double x, y, w, h;
1273 ScTextStream Code(&tmp, QIODevice::ReadOnly);
1274 Code >> command >> subtype >> color >> depth >> pen_style >> font >> font_size >> angle;
1275 Code >> font_flags >> height >> length >> xT >> yT;
1276 text = Code.readAll();
1277 text = cleanText(text);
1278 FPointArray textPath;
1279 QPainterPath painterPath;
1280 QString TFont(m_Doc->itemToolPrefs().textFont);
1281 QFont::Weight weight = QFont::Normal;
1282 bool isItalic = false;
1283 if (font_flags & 4)
1284 {
1285 switch (font)
1286 {
1287 case 0:
1288 TFont = "Times Roman";
1289 weight = QFont::Normal;
1290 break;
1291 case 1:
1292 TFont = "Times Italic";
1293 weight = QFont::Normal;
1294 isItalic = true;
1295 break;
1296 case 2:
1297 TFont = "Times Bold";
1298 weight = QFont::Bold;
1299 break;
1300 case 3:
1301 TFont = "Times Bold Italic";
1302 weight = QFont::Bold;
1303 isItalic = true;
1304 break;
1305 case 4:
1306 TFont = "AvantGarde Book";
1307 weight = QFont::Normal;
1308 break;
1309 case 5:
1310 TFont = "AvantGarde Book Oblique";
1311 weight = QFont::Normal;
1312 break;
1313 case 6:
1314 TFont = "AvantGarde Demi";
1315 weight = QFont::DemiBold;
1316 break;
1317 case 7:
1318 TFont = "AvantGarde Demi Oblique";
1319 weight = QFont::DemiBold;
1320 break;
1321 case 8:
1322 TFont = "Bookman Light";
1323 weight = QFont::Light;
1324 break;
1325 case 9:
1326 TFont = "Bookman Light Italic";
1327 weight = QFont::Light;
1328 isItalic = true;
1329 break;
1330 case 10:
1331 TFont = "Bookman Demi";
1332 weight = QFont::DemiBold;
1333 break;
1334 case 11:
1335 TFont = "Bookman Demi Italic";
1336 weight = QFont::DemiBold;
1337 isItalic = true;
1338 break;
1339 case 12:
1340 TFont = "Courier";
1341 weight = QFont::Normal;
1342 break;
1343 case 13:
1344 TFont = "Courier Oblique";
1345 weight = QFont::Normal;
1346 break;
1347 case 14:
1348 TFont = "Courier Bold";
1349 weight = QFont::Bold;
1350 break;
1351 case 15:
1352 TFont = "Courier Bold Oblique";
1353 weight = QFont::Bold;
1354 break;
1355 case 16:
1356 TFont = "Helvetica";
1357 weight = QFont::Normal;
1358 break;
1359 case 17:
1360 TFont = "Helvetica Oblique";
1361 weight = QFont::Normal;
1362 break;
1363 case 18:
1364 TFont = "Helvetica Bold";
1365 weight = QFont::Bold;
1366 break;
1367 case 19:
1368 TFont = "Helvetica Bold Oblique";
1369 weight = QFont::Bold;
1370 break;
1371 case 20:
1372 TFont = "Helvetica Narrow";
1373 weight = QFont::Normal;
1374 break;
1375 case 21:
1376 TFont = "Helvetica Narrow Oblique";
1377 weight = QFont::Normal;
1378 break;
1379 case 22:
1380 TFont = "Helvetica Narrow Bold";
1381 weight = QFont::Bold;
1382 break;
1383 case 23:
1384 TFont = "Helvetica Narrow Bold Oblique";
1385 weight = QFont::Bold;
1386 break;
1387 case 24:
1388 TFont = "New Century Schoolbook Roman";
1389 weight = QFont::Normal;
1390 break;
1391 case 25:
1392 TFont = "New Century Schoolbook Italic";
1393 weight = QFont::Normal;
1394 isItalic = true;
1395 break;
1396 case 26:
1397 TFont = "New Century Schoolbook Bold";
1398 weight = QFont::Bold;
1399 break;
1400 case 27:
1401 TFont = "New Century Schoolbook Bold Italic";
1402 weight = QFont::Bold;
1403 isItalic = true;
1404 break;
1405 case 28:
1406 TFont = "Palatino Roman";
1407 weight = QFont::Normal;
1408 break;
1409 case 29:
1410 TFont = "Palatino Italic";
1411 weight = QFont::Normal;
1412 isItalic = true;
1413 break;
1414 case 30:
1415 TFont = "Palatino Bold";
1416 weight = QFont::Bold;
1417 break;
1418 case 31:
1419 TFont = "Palatino Bold Italic";
1420 weight = QFont::Bold;
1421 isItalic = true;
1422 break;
1423 case 32:
1424 TFont = "Symbol";
1425 weight = QFont::Normal;
1426 break;
1427 case 33:
1428 TFont = "Zapf Chancery Medium Italic";
1429 weight = QFont::Normal;
1430 isItalic = true;
1431 break;
1432 case 34:
1433 TFont = "Zapf Dingbats";
1434 weight = QFont::Normal;
1435 break;
1436 default:
1437 TFont = m_Doc->itemToolPrefs().textFont;
1438 weight = QFont::Normal;
1439 break;
1440 }
1441 }
1442 else
1443 {
1444 switch (font)
1445 {
1446 case 1: // Roman
1447 TFont = "Times";
1448 weight = QFont::Normal;
1449 break;
1450 case 2: // Bold
1451 TFont = "Times";
1452 weight = QFont::Bold;
1453 break;
1454 case 3: // Italic
1455 TFont = "Times";
1456 weight = QFont::Normal;
1457 isItalic = true;
1458 break;
1459 case 4: // Sans Serif
1460 TFont = "Helvetica";
1461 weight = QFont::Normal;
1462 break;
1463 case 5: // Typewriter
1464 TFont = "Courier";
1465 weight = QFont::Normal;
1466 break;
1467 default:
1468 TFont = m_Doc->itemToolPrefs().textFont;
1469 weight = QFont::Normal;
1470 break;
1471 }
1472 }
1473 w = fig2Pts(length);
1474 h = fig2Pts(height);
1475 x = fig2Pts(xT);
1476 y = fig2Pts(yT);
1477 x -= docX;
1478 x += m_Doc->currentPage()->xOffset();
1479 y -= docY;
1480 y += m_Doc->currentPage()->yOffset();
1481 QFont tf = QFont(TFont, 10, weight, isItalic);
1482 tf.setPointSizeF(font_size / 80.0 * 72.0);
1483 painterPath.addText( 0, 0, tf, text );
1484 QRectF br = painterPath.boundingRect();
1485 if ((angle == 0) && (br.width() > w))
1486 {
1487 QTransform m;
1488 m.scale(w / br.width(), w / br.width());
1489 painterPath = m.map(painterPath);
1490 }
1491 textPath.fromQPainterPath(painterPath);
1492 useColor(color, 0, false);
1493 int z = -1;
1494 PageItem *ite;
1495 z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX + x, baseY + y, w, h, 0, CurrColorStroke, CommonStrings::None);
1496 if (z >= 0)
1497 {
1498 ite = m_Doc->Items->at(z);
1499 ite->setRotation(-angle * 180.0 / M_PI);
1500 ite->PoLine = textPath.copy();
1501 ite->ClipEdited = true;
1502 ite->FrameType = 3;
1503 FPoint wh = getMaxClipF(&ite->PoLine);
1504 ite->setWidthHeight(wh.x(),wh.y());
1505 ite->setTextFlowMode(PageItem::TextFlowDisabled);
1506 m_Doc->adjustItemSize(ite);
1507 ite->setWidthHeight(qMax(ite->width(), 1.0), qMax(ite->height(), 1.0));
1508 if (subtype == 1)
1509 m_Doc->moveRotated(ite, FPoint(-br.width() / 2.0, 0.0));
1510 else if (subtype == 2)
1511 m_Doc->moveRotated(ite, FPoint(-br.width(), 0.0));
1512 depthMap.insert(999 - depth, currentItemNr);
1513 currentItemNr++;
1514 }
1515 }
1516
processData(QDataStream & ts,const QString & data)1517 void XfigPlug::processData(QDataStream &ts, const QString& data)
1518 {
1519 QString tmp = data;
1520 int command, subtype;
1521 ScTextStream Code(&tmp, QIODevice::ReadOnly);
1522 Code >> command >> subtype;
1523 switch (command)
1524 {
1525 case 0:
1526 parseColor(data);
1527 break;
1528 case 1:
1529 processEllipse(data);
1530 break;
1531 case 2:
1532 processPolyline(ts, data);
1533 break;
1534 case 3:
1535 processSpline(ts, data);
1536 break;
1537 case 4:
1538 processText(data);
1539 break;
1540 case 5:
1541 processArc(ts, data);
1542 break;
1543 case 6:
1544 // qDebug() << "Xfig-Import:: Unsupported Compound object";
1545 break;
1546 case -6:
1547 // qDebug() << "Xfig-Import:: Unsupported End of Compound object";
1548 break;
1549 }
1550 }
1551
resortItems()1552 void XfigPlug::resortItems()
1553 {
1554 QList<PageItem*> itemList;
1555 int newItemCount = m_Doc->Items->count();
1556 itemList.reserve(newItemCount - oldDocItemCount);
1557 for (int as = oldDocItemCount; as < newItemCount; ++as)
1558 {
1559 itemList.append(m_Doc->Items->takeAt(oldDocItemCount));
1560 }
1561
1562 QList<int> keylist = depthMap.uniqueKeys();
1563 int keysCount = keylist.count();
1564 int currentLayer = 0;
1565 for (int it = 0; it < keysCount; ++it)
1566 {
1567 if ((importerFlags & LoadSavePlugin::lfCreateDoc) && (it > 0))
1568 currentLayer = m_Doc->addLayer(QString("Layer %1").arg(it), true);
1569 QList<int> elems = depthMap.values(keylist.at(it));
1570 std::sort(elems.begin(), elems.end());
1571 int itemsCount = elems.count();
1572 for (int i = 0; i < itemsCount; ++i)
1573 {
1574 PageItem* ite = itemList.at(elems.at(i));
1575 Elements.append(ite);
1576 m_Doc->Items->append(ite);
1577 if ((importerFlags & LoadSavePlugin::lfCreateDoc) && (it > 0))
1578 ite->m_layerID = currentLayer;
1579 }
1580 }
1581 }
1582
1583
fig2Pts(double in)1584 double XfigPlug::fig2Pts(double in)
1585 {
1586 return in / 1200.0 * 72.0;
1587 }
1588
convert(const QString & fn)1589 bool XfigPlug::convert(const QString& fn)
1590 {
1591 QString tmp;
1592 CurrColorFill = "White";
1593 CurrFillShade = 100.0;
1594 CurrColorStroke = "Black";
1595 CurrStrokeShade = 100.0;
1596 patternMode = false;
1597 patternX1 = 0.0;
1598 patternY1 = 0.0;
1599 patternX2 = 0.0;
1600 patternY2 = 0.0;
1601 Coords.resize(0);
1602 Coords.svgInit();
1603 clipCoords.resize(0);
1604 clipCoords.svgInit();
1605 currentPatternName = "";
1606 currentPatternX = 0.0;
1607 currentPatternY = 0.0;
1608 currentPatternXScale = 1.0;
1609 currentPatternYScale = 1.0;
1610 currentPatternRotation = 0.0;
1611 QList<PageItem*> gElements;
1612 groupStack.push(gElements);
1613 currentItemNr = 0;
1614 if (progressDialog)
1615 {
1616 progressDialog->setOverallProgress(2);
1617 progressDialog->setLabel("GI", tr("Generating Items"));
1618 qApp->processEvents();
1619 }
1620 QFile f(fn);
1621 if (f.open(QIODevice::ReadOnly))
1622 {
1623 oldDocItemCount = m_Doc->Items->count();
1624 int fSize = (int) f.size();
1625 if (progressDialog)
1626 {
1627 progressDialog->setTotalSteps("GI", fSize);
1628 qApp->processEvents();
1629 }
1630 QDataStream ts(&f);
1631 QString version = readLineFromDataStream(ts);
1632 QString orientation = readLineFromDataStream(ts);
1633 QString justification = readLineFromDataStream(ts);
1634 QString units = readLineFromDataStream(ts);
1635 QString papersize = readLineFromDataStream(ts);
1636 QString magnification = readLineFromDataStream(ts);
1637 QString multiple = readLineFromDataStream(ts);
1638 QString transparent = readLineFromDataStream(ts);
1639 tmp = readLineFromDataStream(ts);
1640 if (tmp.startsWith("#"))
1641 tmp = readLineFromDataStream(ts);
1642 QString resolution = tmp;
1643 while (!ts.atEnd())
1644 {
1645 tmp = readLineFromDataStream(ts);
1646 if (tmp.startsWith("#"))
1647 continue;
1648 processData(ts, tmp);
1649 if (progressDialog)
1650 {
1651 progressDialog->setProgress("GI", ts.device()->pos());
1652 qApp->processEvents();
1653 }
1654 }
1655 resortItems();
1656 }
1657 if (progressDialog)
1658 progressDialog->close();
1659 return true;
1660 }
1661