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                           pslib.cpp  -  description
9                              -------------------
10     begin                : Sat May 26 2001
11     copyright            : (C) 2001 by Franz Schmid
12     email                : Franz.Schmid@altmuehlnet.de
13  ***************************************************************************/
14 
15 /***************************************************************************
16  *                                                                         *
17  *   This program is free software; you can redistribute it and/or modify  *
18  *   it under the terms of the GNU General Public License as published by  *
19  *   the Free Software Foundation; either version 2 of the License, or     *
20  *   (at your option) any later version.                                   *
21  *                                                                         *
22  ***************************************************************************/
23 
24 #include "pslib.h"
25 
26 #include <cstdlib>
27 
28 #include <QFileInfo>
29 #include <QImage>
30 #include <QColor>
31 #include <QFontInfo>
32 #include <QList>
33 #include <QByteArray>
34 #include <QRegExp>
35 #include <QBuffer>
36 #include <QStack>
37 
38 #include "api/api_application.h"
39 #include "cmsettings.h"
40 #include "commonstrings.h"
41 #include "scconfig.h"
42 #include "pluginapi.h"
43 #include "pageitemiterator.h"
44 #include "pageitem_latexframe.h"
45 #include "pageitem_table.h"
46 #include "prefsmanager.h"
47 #include "scclocale.h"
48 #include "sccolorengine.h"
49 #include "scfonts.h"
50 #include "scribusapp.h"
51 #include "scribusdoc.h"
52 
53 #include "scribuscore.h"
54 #include "selection.h"
55 #include "scpattern.h"
56 #include "scstreamfilter_ascii85.h"
57 #include "scstreamfilter_flate.h"
58 #include "tableutils.h"
59 #include "text/textlayoutpainter.h"
60 #include "ui/multiprogressdialog.h"
61 #include "util.h"
62 #include "util_formats.h"
63 #include "util_math.h"
64 #include "text/boxes.h"
65 
66 using namespace TableUtils;
67 
68 class PSPainter:public TextLayoutPainter
69 {
70 	public:
PSPainter(ScribusDoc * Doc,uint argh,ScPage * page,bool master,PSLib * ps)71 	PSPainter(ScribusDoc* Doc, uint argh, ScPage* page, bool master, PSLib* ps):
72 		m_Doc(Doc),
73 		m_argh(argh),
74 		m_page(page),
75 		m_master(master),
76 		m_ps(ps)
77 	{}
78 
79 	void drawGlyph(const GlyphCluster& gc) override;
80 	void drawGlyphOutline(const GlyphCluster& gc, bool fill) override;
81 	void drawLine(QPointF start, QPointF end) override;
82 	void drawRect(QRectF rect) override;
83 	void drawObject(PageItem* item) override;
84 
85 	private:
86 		ScribusDoc* m_Doc {nullptr};
87 		uint m_argh;
88 		ScPage* m_page {nullptr};
89 		bool m_master;
90 		PSLib* m_ps {nullptr};
91 
applyTransform()92 		void applyTransform()
93 		{
94 			if (matrix() != QTransform())
95 			{
96 				m_ps->PutStream(m_ps->MatrixToStr(1.0, 0.0, 0.0, -1.0, x(), 0.0) + "\n");
97 				m_ps->PutStream(m_ps->MatrixToStr(matrix().m11(), -matrix().m12(), matrix().m21(), -matrix().m22(), matrix().dx(), -matrix().dy()) + "\n");
98 				m_ps->PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
99 			}
100 		}
101 
102 };
103 
drawGlyph(const GlyphCluster & gc)104 void PSPainter::drawGlyph(const GlyphCluster& gc)
105 {
106 	if (gc.isControlGlyphs() || gc.isEmpty())
107 		return;
108 
109 	m_ps->PS_save();
110 	applyTransform();
111 	m_ps->PS_translate(x(), -(y() - fontSize()));
112 
113 	double current_x = 0.0;
114 	for (const GlyphLayout& gl : gc.glyphs())
115 	{
116 		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
117 		{
118 			current_x += gl.xadvance * gl.scaleH;
119 			continue;
120 		}
121 
122 		m_ps->PS_save();
123 		m_ps->PS_translate(gl.xoffset + current_x, -(fontSize() - fontSize() * gl.scaleV) - gl.yoffset);
124 		if (gl.scaleH != 1.0 || (gl.scaleV != 1.0))
125 			m_ps->PS_scale(gl.scaleH, gl.scaleV);
126 
127 		if (fillColor().color != CommonStrings::None)
128 			m_ps->putColorNoDraw(fillColor().color, fillColor().shade);
129 		m_ps->PS_showSub(gl.glyph, m_ps->FontSubsetMap[font().scName()], fontSize(), false);
130 		m_ps->PS_restore();
131 
132 		current_x += gl.xadvance * gl.scaleH;
133 	}
134 	m_ps->PS_restore();
135 }
136 
drawGlyphOutline(const GlyphCluster & gc,bool fill)137 void PSPainter::drawGlyphOutline(const GlyphCluster& gc, bool fill)
138 {
139 	if (gc.isControlGlyphs() || gc.isEmpty())
140 		return;
141 	if (strokeColor().color == CommonStrings::None)
142 		return;
143 
144 	double h, s, v, k;
145 	QVector<double> dum;
146 
147 	m_ps->PS_save();
148 	applyTransform();
149 	m_ps->PS_setlinewidth(strokeWidth());
150 	m_ps->PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
151 	m_ps->PS_setdash(Qt::SolidLine, 0, dum);
152 	m_ps->PS_translate(x(), -(y() - fontSize()));
153 
154 	double current_x = 0.0;
155 	for (const GlyphLayout& gl : gc.glyphs())
156 	{
157 		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
158 		{
159 			current_x += gl.xadvance * gl.scaleH;
160 			continue;
161 		}
162 
163 		m_ps->PS_save();
164 		FPointArray gly = font().glyphOutline(gl.glyph);
165 		QTransform chma;
166 		chma.scale((fontSize() * gc.scaleH()) / 10.0, (fontSize() * gc.scaleV()) / 10.0);
167 		gly.map(chma);
168 		m_ps->PS_translate(gl.xoffset + current_x, -(fontSize() - fontSize() * gc.scaleV()) - gl.yoffset);
169 
170 		if (fill)
171 		{
172 			m_ps->PS_save();
173 			if (gc.scaleH() != 1.0 || gc.scaleV() != 1.0)
174 				m_ps->PS_scale(gc.scaleH(), gc.scaleV());
175 			m_ps->putColorNoDraw(fillColor().color, fillColor().shade);
176 			m_ps->PS_showSub(gl.glyph, m_ps->FontSubsetMap[font().scName()], fontSize(), false);
177 			m_ps->PS_restore();
178 		}
179 
180 		m_ps->SetColor(strokeColor().color, strokeColor().shade, &h, &s, &v, &k);
181 		m_ps->PS_setcmykcolor_stroke(h, s, v, k);
182 		m_ps->SetClipPath(gly, true);
183 		m_ps->PS_closepath();
184 		m_ps->putColor(strokeColor().color, strokeColor().shade, false);
185 		m_ps->PS_restore();
186 
187 		current_x += gl.xadvance * gl.scaleH;
188 	}
189 
190 	m_ps->PS_restore();
191 }
192 
drawRect(QRectF rect)193 void PSPainter::drawRect(QRectF rect)
194 {
195 	double h {0.0}, s {0.0}, v {0.0}, k {0.0};
196 	m_ps->PS_save();
197 	applyTransform();
198 	m_ps->PS_moveto(x() + rect.x(), -y() - rect.y());
199 	m_ps->PS_lineto(x() + rect.x() + rect.width(), -y() - rect.y());
200 	m_ps->PS_lineto(x() + rect.x() + rect.width(), -y() - rect.y() - rect.height());
201 	m_ps->PS_lineto(x() + rect.x(), -y() - rect.y() - rect.height());
202 	m_ps->PS_closepath();
203 	m_ps->SetColor(fillColor().color, fillColor().shade, &h, &s, &v, &k);
204 	m_ps->PS_setcmykcolor_fill(h, s, v, k);
205 	m_ps->putColor(fillColor().color, fillColor().shade, true);
206 	m_ps->PS_restore();
207 }
208 
drawLine(QPointF start,QPointF end)209 void PSPainter::drawLine(QPointF start, QPointF end)
210 {
211 	QVector<double> dum;
212 	dum.clear();
213 	m_ps->PS_save();
214 	applyTransform();
215 	if (fillColor().color != CommonStrings::None)
216 	{
217 		double h = 0.0;
218 		double s = 0.0;
219 		double v = 0.0;
220 		double k = 0.0;
221 		m_ps->PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
222 		m_ps->PS_setdash(Qt::SolidLine, 0, dum);
223 		m_ps->SetColor(fillColor().color,fillColor().shade, &h, &s, &v, &k);
224 		m_ps->PS_setcmykcolor_stroke(h, s, v, k);
225 	}
226 	m_ps->PS_setlinewidth(strokeWidth());
227 	m_ps->PS_moveto(x() + start.x(), -y() - start.y());
228 	m_ps->PS_lineto(x() + end.x(), -y() - end.y());
229 	m_ps->putColor(fillColor().color, fillColor().shade, false);
230 	m_ps->PS_restore();
231 }
232 
drawObject(PageItem * item)233 void PSPainter::drawObject(PageItem* item)
234 {
235 	m_ps->PS_save();
236 	m_ps->PS_translate(x() + item->gXpos, -(y() + item->gYpos));
237 	applyTransform();
238 	if (scaleH() != 1 || scaleV() != 1)
239 		m_ps->PS_scale(scaleH(), scaleV());
240 	m_ps->ProcessItem(m_page, item, m_argh, m_master, true);
241 	m_ps->PS_restore();
242 }
243 
PSLib(ScribusDoc * doc,PrintOptions & options,OutputFormat outputFmt,ColorList * docColors)244 PSLib::PSLib(ScribusDoc* doc, PrintOptions &options, OutputFormat outputFmt, ColorList *docColors)
245 	: m_Doc(doc), m_outputFormat(outputFmt)
246 {
247 	Options = options;
248 	User = "";
249 	Creator = ScribusAPI::getVersionScribus();
250 	Title = "";
251 	FillColor = "0.0 0.0 0.0 0.0";
252 	StrokeColor = "0.0 0.0 0.0 0.0";
253 	FontDesc = "";
254 	cmykCustomColors = "";
255 	docCustomColors = "";
256 
257 	CMYKColorF cmykValues;
258 	double c, m, y, k;
259 	int spotCount = 1;
260 	bool first = true;
261 	spotMap.clear();
262 	colorDesc.clear();
263 
264 	if (docColors != nullptr)
265 		colorsToUse = *docColors;
266 	else
267 		m_Doc->getUsedColors(colorsToUse);
268 	colorsToUse.setDocument(m_Doc);
269 
270 	for (auto itf = colorsToUse.begin(); itf != colorsToUse.end(); ++itf)
271 	{
272 		if (((itf->isSpotColor()) || (itf->isRegistrationColor())) && (Options.useSpotColors))
273 		{
274 			ScColorEngine::getCMYKValues(*itf, colorsToUse.document(), cmykValues);
275 			cmykValues.getValues(c, m, y, k);
276 			colorDesc += "/Spot" + QString::number(spotCount) + " { [ /Separation (";
277 			if (itf->isRegistrationColor())
278 				colorDesc += "All";
279 			else
280 				colorDesc += itf.key();
281 			colorDesc += ")\n";
282 			colorDesc += "/DeviceCMYK\n{\ndup " + ToStr(c) + "\nmul exch dup ";
283 			colorDesc += ToStr(m) + "\nmul exch dup ";
284 			colorDesc += ToStr(y) + "\nmul exch ";
285 			colorDesc += ToStr(k) + " mul }] setcolorspace setcolor} bind def\n";
286 			spotMap.insert(itf.key(), "Spot" + QString::number(spotCount));
287 			++spotCount;
288 		}
289 		if ((itf.key() != "Cyan") && (itf.key() != "Magenta") && (itf.key() != "Yellow") && (itf.key() != "Black") && itf->isSpotColor())
290 		{
291 			ScColorEngine::getCMYKValues(colorsToUse[itf.key()], colorsToUse.document(), cmykValues);
292 			cmykValues.getValues(c, m, y, k);
293 			if (!first)
294 			{
295 				cmykCustomColors += "%%+ ";
296 				docCustomColors += "%%+ ";
297 			}
298 			cmykCustomColors += ToStr(c) + " " + ToStr(m) + " ";
299 			cmykCustomColors += ToStr(y) + " " + ToStr(k) + " (" + itf.key() + ")\n";
300 			docCustomColors += "(" + itf.key() + ")\n";
301 			first = false;
302 		}
303 	}
304 
305 	QMap<QString, QString> psNameMap;
306 	SCFonts& allFonts = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts;
307 	QMap<QString, QMap<uint, QString> > docFonts;
308 	doc->getUsedFonts(docFonts);
309 
310 	for (auto it = docFonts.begin(); it != docFonts.end(); ++it)
311 	{
312 		// Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed
313 		// Subset also font whose postscript name conflicts with an already used font
314 		// Subset always now with new boxes code.
315 		ScFace &face (allFonts[it.key()]);
316 		QMap<uint, QString>& usedGlyphs(it.value());
317 		QString encodedName = face.psName().simplified().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" );
318 
319 		// Handle possible PostScript name conflict in oft/ttf fonts
320 		int psNameIndex = 1;
321 		QString initialName = encodedName;
322 		while (psNameMap.contains(encodedName))
323 		{
324 			encodedName = QString("%1-%2").arg(initialName).arg(psNameIndex);
325 			++psNameIndex;
326 		}
327 		FontDesc += "/" + encodedName + " " + IToStr(usedGlyphs.count() + 1) + " dict def\n";
328 		FontDesc += encodedName + " begin\n";
329 
330 		for (auto ig = usedGlyphs.begin(); ig != usedGlyphs.end(); ++ig)
331 		{
332 			uint gid = ig.key();
333 			FPointArray glyphOutline = face.glyphOutline(gid);
334 
335 			FontDesc += "/G" + IToStr(gid) + " { newpath\n";
336 			FPoint np, np1, np2;
337 			bool nPath = true;
338 			if (glyphOutline.size() > 3)
339 			{
340 				for (int poi = 0; poi < glyphOutline.size() - 3; poi += 4)
341 				{
342 					if (glyphOutline.isMarker(poi))
343 					{
344 						FontDesc += "cl\n";
345 						nPath = true;
346 						continue;
347 					}
348 					if (nPath)
349 					{
350 						np = glyphOutline.point(poi);
351 						FontDesc += ToStr(np.x()) + " " + ToStr(-np.y()) + " m\n";
352 						nPath = false;
353 					}
354 					np = glyphOutline.point(poi + 1);
355 					np1 = glyphOutline.point(poi + 3);
356 					np2 = glyphOutline.point(poi + 2);
357 					FontDesc += ToStr(np.x()) + " " + ToStr(-np.y()) + " " +
358 							ToStr(np1.x()) + " " + ToStr(-np1.y()) + " " +
359 							ToStr(np2.x()) + " " + ToStr(-np2.y()) + " cu\n";
360 				}
361 			}
362 			FontDesc += "cl\n} bind def\n";
363 		}
364 		FontDesc += "end\n";
365 		FontSubsetMap.insert(face.scName(), encodedName);
366 
367 		psNameMap.insert(encodedName, face.scName());
368 	}
369 }
370 
~PSLib()371 PSLib::~PSLib()
372 {
373 	if (progressDialog)
374 		progressDialog->deleteLater();
375 }
376 
PutStream(const QString & c)377 void PSLib::PutStream(const QString& c)
378 {
379 	QByteArray utf8Array = c.toUtf8();
380 	spoolStream.writeRawData(utf8Array.data(), utf8Array.length());
381 }
382 
PutStream(const QByteArray & array,bool hexEnc)383 void PSLib::PutStream(const QByteArray& array, bool hexEnc)
384 {
385 	if (hexEnc)
386 		WriteASCII85Bytes(array);
387 	else
388 		spoolStream.writeRawData(array.data(), array.size());
389 }
390 
PutStream(const char * array,int length,bool hexEnc)391 void PSLib::PutStream(const char* array, int length, bool hexEnc)
392 {
393 	if (hexEnc)
394 		WriteASCII85Bytes((const unsigned char*) array, length);
395 	else
396 		spoolStream.writeRawData(array, length);
397 }
398 
PutImageToStream(ScImage & image,int plate)399 bool PSLib::PutImageToStream(ScImage& image, int plate)
400 {
401 	bool writeSucceed = false;
402 	ScASCII85EncodeFilter asciiEncode(&spoolStream);
403 	ScFlateEncodeFilter   flateEncode(&asciiEncode);
404 	if (flateEncode.openFilter())
405 	{
406 		writeSucceed  = image.writePSImageToFilter(&flateEncode, plate);
407 		writeSucceed &= flateEncode.closeFilter();
408 	}
409 	return writeSucceed;
410 }
411 
PutImageToStream(ScImage & image,const QByteArray & mask,int plate)412 bool PSLib::PutImageToStream(ScImage& image, const QByteArray& mask, int plate)
413 {
414 	bool writeSucceed = false;
415 	ScASCII85EncodeFilter asciiEncode(&spoolStream);
416 	ScFlateEncodeFilter   flateEncode(&asciiEncode);
417 	if (flateEncode.openFilter())
418 	{
419 		writeSucceed  = image.writePSImageToFilter(&flateEncode, mask, plate);
420 		writeSucceed &= flateEncode.closeFilter();
421 	}
422 	return writeSucceed;
423 }
424 
PutImageDataToStream(const QByteArray & image)425 bool PSLib::PutImageDataToStream(const QByteArray& image)
426 {
427 	bool writeSucceed = false;
428 	ScASCII85EncodeFilter asciiEncode(&spoolStream);
429 	ScFlateEncodeFilter   flateEncode(&asciiEncode);
430 	if (flateEncode.openFilter())
431 	{
432 		writeSucceed  = flateEncode.writeData(image, image.size());
433 		writeSucceed &= flateEncode.closeFilter();
434 	}
435 	return writeSucceed;
436 }
437 
PutInterleavedImageMaskToStream(const QByteArray & image,const QByteArray & mask,bool gray)438 bool PSLib::PutInterleavedImageMaskToStream(const QByteArray& image, const QByteArray& mask, bool gray)
439 {
440 	int pending = 0;
441 	unsigned char bytes[1505];
442 	const unsigned char* imageData = (const unsigned char*) image.constData();
443 	const unsigned char* maskData  = (const unsigned char*) mask.constData();
444 	bool  writeSuccess = true;
445 
446 	int channels = gray ? 1 : 4;
447 	int pixels   = image.size() / channels;
448 	assert((image.size() % channels) == 0);
449 	assert( mask.size() >= pixels );
450 
451 	ScASCII85EncodeFilter asciiEncode(&spoolStream);
452 	ScFlateEncodeFilter   flateEncode(&asciiEncode);
453 	if (!flateEncode.openFilter())
454 		return false;
455 
456 	for (int i = 0; i < pixels; ++i)
457 	{
458 		bytes[pending++] = maskData [i];
459 		bytes[pending++] = *imageData++; // cyan/black
460 		if (channels > 1)
461 		{
462 			bytes[pending++] = *imageData++; // magenta
463 			bytes[pending++] = *imageData++; // yellow
464 			bytes[pending++] = *imageData++; // green
465 		}
466 		if (pending >= 1500)
467 		{
468 			writeSuccess &= flateEncode.writeData((const char* ) bytes, pending);
469 			pending = 0;
470 		}
471 	}
472 	// To close the stream
473 	if (pending > 0)
474 		writeSuccess &= flateEncode.writeData((const char* ) bytes, pending);
475 	writeSuccess &= flateEncode.closeFilter();
476 	return writeSuccess;
477 }
478 
WriteASCII85Bytes(const QByteArray & array)479 void PSLib::WriteASCII85Bytes(const QByteArray& array)
480 {
481 	WriteASCII85Bytes((const unsigned char*) array.data(), array.size());
482 }
483 
WriteASCII85Bytes(const unsigned char * array,int length)484 void PSLib::WriteASCII85Bytes(const unsigned char* array, int length)
485 {
486 	ScASCII85EncodeFilter filter(&spoolStream);
487 	filter.openFilter();
488 	filter.writeData((const char*) array, length);
489 	filter.closeFilter();
490 }
491 
ToStr(double c)492 QString PSLib::ToStr(double c)
493 {
494 	QString cc;
495 	return cc.setNum(c);
496 }
497 
IToStr(int c)498 QString PSLib::IToStr(int c)
499 {
500 	QString cc;
501 	return cc.setNum(c);
502 }
503 
MatrixToStr(double m11,double m12,double m21,double m22,double x,double y)504 QString PSLib::MatrixToStr(double m11, double m12, double m21, double m22, double x, double y)
505 {
506 	QString cc("[%1 %2 %3 %4 %5 %6]");
507 	return  cc.arg(m11).arg(m12).arg(m21).arg(m22).arg(x).arg(y);
508 }
509 
PS_set_Info(const QString & art,const QString & was)510 void PSLib::PS_set_Info(const QString& art, const QString& was)
511 {
512 	if (art == "Author")
513 		User = was;
514 	if (art == "Creator")
515 		Creator = was;
516 	if (art == "Title")
517 		Title = was;
518 }
519 
PS_set_file(const QString & fn)520 bool PSLib::PS_set_file(const QString& fn)
521 {
522 	Spool.setFileName(fn);
523 	if (Spool.exists())
524 		Spool.remove();
525 	bool ret = Spool.open(QIODevice::WriteOnly);
526 	if (!ret)
527 	{
528 		PS_Error( tr("Failed to open file for writing : %1").arg(fn) );
529 		return false;
530 	}
531 	spoolStream.setDevice(&Spool);
532 	return true;
533 }
534 
PS_begin_doc(double x,double y,double width,double height,int numpage)535 bool PSLib::PS_begin_doc(double x, double y, double width, double height, int numpage)
536 {
537 	QString header = (m_outputFormat == OutputPS) ? "%!PS-Adobe-3.0\n" : "%!PS-Adobe-3.0 EPSF-3.0\n";
538 	PutStream(header);
539 	PutStream("%%For: " + User + "\n");
540 	PutStream("%%Title: " + Title + "\n");
541 	PutStream("%%Creator: " + Creator + "\n");
542 	PutStream("%%Pages: " + IToStr(numpage) + "\n");
543 
544 	QString bbox, bboxH;
545 	if ((width <= height) || (m_outputFormat == OutputEPS))
546 	{
547 		bbox = "%%BoundingBox: " + IToStr(qRound(x)) + " " + IToStr(qRound(y)) + " " + IToStr(qRound(width)) + " " + IToStr(qRound(height)) + "\n";
548 		bboxH = "%%HiResBoundingBox: " + ToStr(x) + " " + ToStr(y) + " " + ToStr(width) + " " + ToStr(height) + "\n";
549 	}
550 	else
551 	{
552 		bbox = "%%BoundingBox: " + IToStr(qRound(x)) + " " + IToStr(qRound(y)) + " " + IToStr(qRound(height)) + " " + IToStr(qRound(width)) + "\n";
553 		bboxH = "%%HiResBoundingBox: " + ToStr(x) + " " + ToStr(y) + " " + ToStr(height) + " " + ToStr(width) + "\n";
554 	}
555 	PutStream(bbox);
556 	PutStream(bboxH);
557 
558 	if (!docCustomColors.isEmpty())
559 		PutStream("%%DocumentCustomColors: " + docCustomColors);
560 	if (!cmykCustomColors.isEmpty())
561 		PutStream("%%CMYKCustomColor: " + cmykCustomColors);
562 	PutStream("%%LanguageLevel: 3\n");
563 	PutStream("%%EndComments\n");
564 	if ((m_outputFormat == OutputPS) && Options.setDevParam)
565 	{
566 		PutStream("%%BeginDefaults\n");
567 		if (width <= height)
568 			PutStream("%%ViewingOrientation: 1 0 0 1\n");
569 		else
570 			PutStream("%%ViewingOrientation: 0 1 -1 0\n");
571 		PutStream("%%EndDefaults\n");
572 	}
573 	else if (m_outputFormat == OutputEPS)
574 	{
575 		PutStream("%%BeginDefaults\n");
576 		PutStream("%%ViewingOrientation: 1 0 0 1\n");
577 		PutStream("%%EndDefaults\n");
578 	}
579 
580 	QString prolog = "%%BeginProlog\n";
581 	prolog += "/Scribusdict 100 dict def\n";
582 	prolog += "Scribusdict begin\n";
583 	prolog += "/sp {showpage} bind def\n";
584 	prolog += "/oldsetgray /setgray load def\n";
585 	prolog += "/cmyk {setcmykcolor} def\n";
586 	prolog += "/m {moveto} bind def\n";
587 	prolog += "/l {lineto} bind def\n";
588 	prolog += "/li {lineto} bind def\n";
589 	prolog += "/cu {curveto} bind def\n";
590 	prolog += "/cl {closepath} bind def\n";
591 	prolog += "/gs {gsave} bind def\n";
592 	prolog += "/gr {grestore} bind def\n";
593 	prolog += "/tr {translate} bind def\n";
594 	prolog += "/ro {rotate} bind def\n";
595 	prolog += "/sh {show} bind def\n";
596 	prolog += "/shg {setcmykcolor moveto glyphshow} def\n";
597 	prolog += "/shgsp {moveto glyphshow} def\n";
598 	prolog += "/sc {scale} bind def\n";
599 	prolog += "/se {selectfont} bind def\n";
600 	prolog += "/sf {setfont} bind def\n";
601 	prolog += "/sw {setlinewidth} bind def\n";
602 	prolog += "/f  {findfont} bind def\n";
603 	prolog += "/fi {fill} bind def\n";
604 	prolog += "/st {stroke} bind def\n";
605 	prolog += "/shgf {gs dup scale begin cvx exec fill end gr} bind def\n";
606 	prolog += "/shgs {gs dup 1 exch div currentlinewidth mul sw dup scale\n";
607 	prolog += "       begin cvx exec st end gr} bind def\n";
608 	prolog += "/bEPS {\n";
609 	prolog += "    /b4_Inc_state save def\n";
610 	prolog += "    /dict_count countdictstack def\n";
611 	prolog += "    /op_count count 1 sub def\n";
612 	prolog += "    userdict begin\n";
613 	prolog += "    /showpage { } def\n";
614 	prolog += "    0 setgray 0 setlinecap\n";
615 	prolog += "    1 setlinewidth 0 setlinejoin\n";
616 	prolog += "    10 setmiterlimit [ ] 0 setdash newpath\n";
617 	prolog += "    /languagelevel where\n";
618 	prolog += "    {pop languagelevel\n";
619 	prolog += "    1 ne\n";
620 	prolog += "    {false setstrokeadjust false setoverprint\n";
621 	prolog += "    } if } if } bind def\n";
622 	prolog += "/eEPS { count op_count sub {pop} repeat\n";
623 	prolog += "    countdictstack dict_count sub {end} repeat\n";
624 	prolog += "    b4_Inc_state restore } bind def\n";
625 	prolog += "    end\n";
626 	if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
627 		prolog += "/rb { [ /Separation (All)\n/DeviceCMYK { dup 0 mul exch dup 0 mul exch dup 0 mul exch 1 mul }\n] setcolorspace setcolor} bind def\n";
628 	prolog += "%%EndProlog\n";
629 	PutStream(prolog);
630 
631 	PutStream("%%BeginSetup\n");
632 	if (Options.includePDFMarks)
633 		PutStream("/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse\n");
634 	if (!FontDesc.isEmpty())
635 		PutStream(FontDesc);
636 	if ((!colorDesc.isEmpty()) && (!Options.outputSeparations))
637 		PutStream(colorDesc);
638 	if (GraySc)
639 	{
640 		QString grayCalc =  "/setcmykcolor {exch 0.11 mul add exch 0.59 mul add exch 0.3 mul add\n";
641 		grayCalc += "               dup 1 gt {pop 1} if 1 exch sub oldsetgray} bind def\n";
642 		grayCalc += "/setrgbcolor {0.11 mul exch 0.59 mul add exch 0.3 mul add\n";
643 		grayCalc += "              oldsetgray} bind def\n";
644 		PutStream(grayCalc);
645 	}
646 
647 	Optimization optim = m_optimization;
648 	m_optimization = OptimizeSize;
649 	QStringList patterns = m_Doc->getPatternDependencyList(m_Doc->getUsedPatterns());
650 	for (int i = 0; i < patterns.count(); ++i)
651 	{
652 		QString patternName(patterns.at(i));
653 		ScPattern pa = m_Doc->docPatterns[patternName];
654 		for (PageItemIterator it(pa.items); *it; ++it)
655 		{
656 			PageItem* item = *it;
657 			if ((item->isImageFrame()) && (item->imageIsAvailable) && (!item->Pfile.isEmpty()) && (item->printEnabled()) && (!Options.outputSeparations) && (Options.useColor))
658 			{
659 				if (!PS_ImageData(item, item->Pfile, item->itemName(), item->ImageProfile, item->UseEmbedded))
660 					return false;
661 			}
662 		}
663 		uint patHash = qHash(patternName);
664 		PutStream("/Pattern" + QString::number(patHash) + " 8 dict def\n");
665 		PutStream("Pattern" + QString::number(patHash) + " begin\n");
666 		PutStream("/PatternType 1 def\n");
667 		PutStream("/PaintType 1 def\n");
668 		PutStream("/TilingType 1 def\n");
669 		PutStream("/BBox [ 0 0 " + ToStr(pa.width) + " " + ToStr(pa.height) + "] def\n");
670 		PutStream("/XStep " + ToStr(pa.width) + " def\n");
671 		PutStream("/YStep " + ToStr(pa.height) + " def\n");
672 		PutStream("/PaintProc {\n");
673 		QIODevice *spStream = spoolStream.device();
674 		QByteArray buf;
675 		// Qt4 QBuffer b(buf);
676 		QBuffer b(&buf);
677 		b.open( QIODevice::WriteOnly );
678 		spoolStream.setDevice(&b);
679 //		PS_translate(pa.items.at(0)->gXpos, -pa.items.at(0)->gYpos);
680 		for (int j = 0; j < pa.items.count(); ++j)
681 		{
682 			PageItem* item = pa.items.at(j);
683 			PutStream("{\n");
684 			PS_save();
685 			PS_translate(item->gXpos, pa.height - item->gYpos);
686 			ProcessItem(m_Doc->Pages->at(0), item, 0, false, true, true);
687 			PS_restore();
688 			PutStream("} exec\n");
689 		}
690 		spoolStream.setDevice(spStream);
691 		PutStream(buf);
692 		PutStream("} def\n");
693 		PutStream("end\n");
694 	}
695 	m_optimization = optim;
696 
697 	bool errorOccured = false;
698 	for (int ap = 0; ap < m_Doc->MasterPages.count() && !abortExport && !errorOccured; ++ap)
699 	{
700 		if (progressDialog)
701 		{
702 			progressDialog->setOverallProgress(ap);
703 			progressDialog->setProgress("EMP", ap);
704 			ScQApp->processEvents();
705 		}
706 		if (m_Doc->MasterItems.count() <= 0)
707 			continue;
708 
709 		ScLayer ll;
710 		ll.isPrintable = false;
711 		ll.ID = 0;
712 		for (int layerLevel = 0; layerLevel < m_Doc->Layers.count() && !abortExport && !errorOccured; ++layerLevel)
713 		{
714 			m_Doc->Layers.levelToLayer(ll, layerLevel);
715 			if (!ll.isPrintable)
716 				continue;
717 			for (int api = 0; api < m_Doc->MasterItems.count() && !abortExport; ++api)
718 			{
719 				PageItem *it = m_Doc->MasterItems.at(api);
720 				if (progressDialog)
721 					ScQApp->processEvents();
722 				if ((it->m_layerID != ll.ID) || (!it->printEnabled()))
723 					continue;
724 				double bLeft, bRight, bBottom, bTop;
725 				GetBleeds(m_Doc->MasterPages.at(ap), bLeft, bRight, bBottom, bTop);
726 				double x1 = m_Doc->MasterPages.at(ap)->xOffset() - bLeft;
727 				double y1 = m_Doc->MasterPages.at(ap)->yOffset() - bTop;
728 				double w1 = m_Doc->MasterPages.at(ap)->width() + bLeft + bRight;
729 				double h1 = m_Doc->MasterPages.at(ap)->height()+ bBottom + bTop;
730 				double lw = it->visualLineWidth();
731 				double x2 = it->BoundingX - lw / 2.0;
732 				double y2 = it->BoundingY - lw / 2.0;
733 				double w2 = qMax(it->BoundingW + lw, 1.0);
734 				double h2 = qMax(it->BoundingH + lw, 1.0);
735 				if (!QRectF(x2, y2, w2, h2).intersects(QRectF(x1, y1, w1, h1)))
736 					continue;
737 				if ((it->OwnPage != m_Doc->MasterPages.at(ap)->pageNr()) && (it->OwnPage != -1))
738 					continue;
739 				if ((m_optimization == OptimizeSize) && it->isImageFrame() && it->imageIsAvailable && (!it->Pfile.isEmpty()) && it->printEnabled() && (!Options.outputSeparations) && Options.useColor)
740 				{
741 					errorOccured = !PS_ImageData(it, it->Pfile, it->itemName(), it->ImageProfile, it->UseEmbedded);
742 					if (errorOccured) break;
743 				}
744 				PS_TemplateStart(QString("mp_obj_%1_%2").arg(ap).arg(qHash(it)));
745 				ProcessItem(m_Doc->MasterPages.at(ap), it, ap+1, true);
746 				PS_TemplateEnd();
747 			}
748 			if (errorOccured) break;
749 		}
750 	}
751 	PutStream("%%EndSetup\n");
752 
753 	return (!errorOccured);
754 }
755 
PSEncode(const QString & in)756 QString PSLib::PSEncode(const QString& in)
757 {
758 	static QRegExp badchars("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]");
759 	QString tmp(in.simplified().replace( badchars, "_" ));
760 	return tmp;
761 }
762 
PS_TemplateStart(const QString & Name)763 void PSLib::PS_TemplateStart(const QString& Name)
764 {
765 	PutStream("/" + PSEncode(Name) + "\n{\n");
766 }
767 
PS_UseTemplate(const QString & Name)768 void PSLib::PS_UseTemplate(const QString& Name)
769 {
770 	PutStream(PSEncode(Name) + "\n");
771 }
772 
PS_TemplateEnd()773 void PSLib::PS_TemplateEnd()
774 {
775 	PutStream("} bind def\n");
776 }
777 
PS_begin_page(ScPage * pg,MarginStruct * Ma,bool clipping)778 void PSLib::PS_begin_page(ScPage* pg, MarginStruct* Ma, bool clipping)
779 {
780 	double bleedRight = 0.0;
781 	double bleedLeft = 0.0;
782 	double markOffs = 0.0;
783 	if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
784 		markOffs = Options.markLength + Options.markOffset;
785 	if ((Options.registrationMarks) || (Options.colorMarks))
786 		markOffs = qMax(markOffs, Options.markOffset + 20.0);
787 	GetBleeds(pg, bleedLeft, bleedRight);
788 	double maxBoxX = pg->width() + bleedLeft + bleedRight + markOffs * 2.0;
789 	double maxBoxY = pg->height() + Options.bleeds.bottom() + Options.bleeds.top() + markOffs * 2.0;
790 	PageIndex++;
791 	PutStream("%%Page: " + IToStr(PageIndex) + " " + IToStr(PageIndex) + "\n");
792 	if (m_outputFormat == OutputPS)
793 	{
794 		if (pg->orientation() == 0)
795 		{
796 			PutStream("%%PageOrientation: Portrait\n");
797 			PutStream("%%PageBoundingBox: 0 0 " + IToStr(qRound(maxBoxX)) + " " + IToStr(qRound(maxBoxY)) + "\n");
798 			PutStream("%%PageCropBox: " + ToStr(bleedLeft + markOffs) + " " + ToStr(Options.bleeds.bottom() + markOffs) + " " + ToStr(maxBoxX - bleedRight - markOffs * 2.0) + " " + ToStr(maxBoxY - Options.bleeds.top() - markOffs * 2.0) + "\n");
799 		}
800 		else
801 		{
802 			PutStream("%%PageOrientation: Landscape\n");
803 			PutStream("%%PageBoundingBox: 0 0 " + IToStr(qRound(maxBoxY)) + " " + IToStr(qRound(maxBoxX)) + "\n");
804 			PutStream("%%PageCropBox: " + ToStr(bleedLeft + markOffs) + " " + ToStr(Options.bleeds.bottom() + markOffs) + " " + ToStr(maxBoxY - Options.bleeds.top() - markOffs * 2.0) + " " + ToStr(maxBoxX - bleedRight - markOffs * 2.0) + "\n");
805 		}
806 	}
807 	PutStream("Scribusdict begin\n");
808 	if ((m_outputFormat == OutputPS) && (Options.setDevParam))
809   	{
810 		if (pg->orientation() == 0)
811 			PutStream("<< /PageSize [ " + ToStr(maxBoxX) + " " + ToStr(maxBoxY) + " ]\n");
812 		else
813 			PutStream("<< /PageSize [ " + ToStr(maxBoxY) + " " + ToStr(maxBoxX) + " ]\n");
814 		PutStream(">> setpagedevice\n");
815 	}
816 	PutStream("save\n");
817 	if ((pg->orientation() == 1) && (m_outputFormat == OutputPS))
818 		PutStream("90 rotate 0 " + IToStr(qRound(maxBoxY)) + " neg translate\n");
819 	PutStream("/DeviceCMYK setcolorspace\n");
820 	// Clip to bleeds
821 	QString clipStr;
822 	double bbWidth  = pg->width()  + bleedLeft + bleedRight;
823 	double bbHeight = pg->height() + Options.bleeds.bottom() + Options.bleeds.top();
824 	clipStr += ToStr(markOffs) + " " + ToStr(markOffs) + " m\n";
825 	clipStr += ToStr(markOffs + bbWidth) + " " + ToStr(markOffs) + " li\n";
826 	clipStr += ToStr(markOffs + bbWidth) + " " + ToStr(markOffs + bbHeight) + " li\n";
827 	clipStr += ToStr(markOffs) + " " + ToStr(markOffs + bbHeight) + " li cl clip newpath\n";
828 	PutStream(clipStr);
829 	// Move to page origin
830 	PutStream(ToStr(bleedLeft + markOffs) + " " + ToStr(Options.bleeds.bottom() + markOffs) + " tr\n");
831 	m_currentPage = pg;
832 	// Clip to margins if requested
833 	if (clipping)
834 	{
835 		QString clipPath = ToStr(Ma->left()) + " " + ToStr(Ma->bottom()) + " m\n";
836 		clipPath += ToStr(pg->width() - Ma->right()) + " " + ToStr(Ma->bottom()) + " li\n";
837 		clipPath += ToStr(pg->width() - Ma->right()) + " " + ToStr(pg->height() - Ma->top()) + " li\n";
838 		clipPath += ToStr(Ma->left()) + " " + ToStr(pg->height() - Ma->top()) + " li cl clip newpath\n";
839 		PutStream(clipPath);
840 	}
841 }
842 
PS_end_page()843 void PSLib::PS_end_page()
844 {
845 	PutStream("%%PageTrailer\nrestore\n");
846 	double markOffs = 0.0;
847 	if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
848 		markOffs = Options.markLength + Options.markOffset;
849 	if ((Options.registrationMarks) || (Options.colorMarks))
850 		markOffs = qMax(markOffs, Options.markOffset + 20.0);
851 	double markDelta = markOffs - (Options.markLength + Options.markOffset);
852 	double bleedRight, bleedLeft;
853 	GetBleeds(m_currentPage, bleedLeft, bleedRight);
854 	double maxBoxX = m_currentPage->width() + bleedLeft + bleedRight + markOffs * 2.0;
855 	double maxBoxY = m_currentPage->height() + Options.bleeds.bottom() + Options.bleeds.top() + markOffs * 2.0;
856 	PutStream("gs\n");
857 	if ((m_currentPage->orientation() == 1) && (m_outputFormat == OutputPS))
858 		PutStream("90 rotate 0 " + IToStr(qRound(maxBoxY)) + " neg translate\n");
859 	if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
860 	{
861 		PutStream("gs\n");
862 		PS_setlinewidth(0.5);
863 		PutStream("[] 0 setdash\n");
864 		PutStream("0 setlinecap\n");
865 		PutStream("0 setlinejoin\n");
866 		PutStream("1 rb\n");
867 		if (Options.cropMarks)
868 		{
869 		// Bottom Left
870 			PutStream(ToStr(markDelta) + " " + ToStr(markOffs + Options.bleeds.bottom()) + " m\n");
871 			PutStream(ToStr(markDelta + Options.markLength) + " " + ToStr(markOffs + Options.bleeds.bottom()) + " li\n");
872 			PutStream("st\n");
873 			PutStream(ToStr(markOffs + bleedLeft) + " " + ToStr(markDelta) + " m\n");
874 			PutStream(ToStr(markOffs + bleedLeft) + " " + ToStr(markDelta + Options.markLength) + " li\n");
875 			PutStream("st\n");
876 		// Top Left
877 			PutStream(ToStr(markDelta) + " " + ToStr(maxBoxY - Options.bleeds.top() - markOffs) + " m\n");
878 			PutStream(ToStr(markDelta + Options.markLength) + " " + ToStr(maxBoxY - Options.bleeds.top() - markOffs) + " li\n");
879 			PutStream("st\n");
880 			PutStream(ToStr(markOffs + bleedLeft) + " " + ToStr(maxBoxY - markDelta) + " m\n");
881 			PutStream(ToStr(markOffs + bleedLeft) + " " + ToStr(maxBoxY - markDelta - Options.markLength)  + " li\n");
882 			PutStream("st\n");
883 		// Bottom Right
884 			PutStream(ToStr(maxBoxX - markDelta) + " " + ToStr(markOffs + Options.bleeds.bottom()) + " m\n");
885 			PutStream(ToStr(maxBoxX - markDelta - Options.markLength) + " " + ToStr(markOffs + Options.bleeds.bottom()) + " li\n");
886 			PutStream("st\n");
887 			PutStream(ToStr(maxBoxX - bleedRight - markOffs) + " " +  ToStr(markDelta) + " m\n");
888 			PutStream(ToStr(maxBoxX - bleedRight - markOffs) + " " +  ToStr(markDelta + Options.markLength)  + " li\n");
889 			PutStream("st\n");
890 		// Top Right
891 			PutStream(ToStr(maxBoxX - markDelta) + " " + ToStr(maxBoxY - Options.bleeds.top() - markOffs) + " m\n");
892 			PutStream(ToStr(maxBoxX - markDelta - Options.markLength) + " " + ToStr(maxBoxY - Options.bleeds.top() - markOffs) + " li\n");
893 			PutStream("st\n");
894  			PutStream(ToStr(maxBoxX - bleedRight - markOffs) + " " +  ToStr(maxBoxY - markDelta) + " m\n");
895 			PutStream(ToStr(maxBoxX - bleedRight - markOffs) + " " +  ToStr(maxBoxY - markDelta - Options.markLength)  + " li\n");
896 			PutStream("st\n");
897 		}
898 		if (Options.bleedMarks)
899 		{
900 			PutStream("gs\n");
901 			PutStream("[3 1 1 1] 0 setdash\n");
902 		// Bottom Left
903 			PutStream(ToStr(markDelta) + " " + ToStr(markOffs) + " m\n");
904 			PutStream(ToStr(markDelta + Options.markLength) + " " + ToStr(markOffs) + " li\n");
905 			PutStream("st\n");
906 			PutStream(ToStr(markOffs) + " " + ToStr(markDelta) + " m\n");
907 			PutStream(ToStr(markOffs) + " " + ToStr(markDelta + Options.markLength) + " li\n");
908 			PutStream("st\n");
909 		// Top Left
910 			PutStream(ToStr(markDelta) + " " + ToStr(maxBoxY - markOffs) + " m\n");
911 			PutStream(ToStr(markDelta + Options.markLength) + " " + ToStr(maxBoxY - markOffs) + " li\n");
912 			PutStream("st\n");
913 			PutStream(ToStr(markOffs) + " " + ToStr(maxBoxY - markDelta) + " m\n");
914 			PutStream(ToStr(markOffs) + " " + ToStr(maxBoxY - markDelta - Options.markLength) + " li\n");
915 			PutStream("st\n");
916 		// Bottom Right
917 			PutStream(ToStr(maxBoxX - markDelta) + " " + ToStr(markOffs) + " m\n");
918 			PutStream(ToStr(maxBoxX - markDelta - Options.markLength) + " " + ToStr(markOffs) + " li\n");
919 			PutStream("st\n");
920 			PutStream(ToStr(maxBoxX - markOffs) + " " + ToStr(markDelta) + " m\n");
921 			PutStream(ToStr(maxBoxX - markOffs) + " " + ToStr(markDelta + Options.markLength) + " li\n");
922 			PutStream("st\n");
923 		// Top Right
924 			PutStream(ToStr(maxBoxX - markDelta) + " " + ToStr(maxBoxY - markOffs) + " m\n");
925 			PutStream(ToStr(maxBoxX - markDelta - Options.markLength) + " " + ToStr(maxBoxY - markOffs) + " li\n");
926 			PutStream("st\n");
927 			PutStream(ToStr(maxBoxX - markOffs) + " " + ToStr(maxBoxY - markDelta) + " m\n");
928 			PutStream(ToStr(maxBoxX - markOffs) + " " + ToStr(maxBoxY - markDelta - Options.markLength) + " li\n");
929 			PutStream("st\n");
930 			PutStream("gr\n");
931 		}
932 		if (Options.registrationMarks)
933 		{
934 			double regDelta  = markOffs - Options.markOffset;
935 			QString regCross = "0 7 m\n14 7 li\n7 0 m\n7 14 li\n13 7 m\n13 10.31383 10.31383 13 7 13 cu\n3.68629 13 1 10.31383 1 7 cu\n1 3.68629 3.68629 1 7 1 cu\n";
936 			regCross += "10.31383 1 13 3.68629 13 7 cu\ncl\n10.5 7 m\n10.5 8.93307 8.93307 10.5 7 10.5 cu\n5.067 10.5 3.5 8.93307 3.5 7 cu\n";
937 			regCross += "3.5 5.067 5.067 3.5 7 3.5 cu\n8.93307 3.5 10.5 5.067 10.5 7 cu\ncl\nst\n";
938 			PutStream("gs\n");
939 			PutStream(ToStr(maxBoxX / 2.0 - 7.0) + " " + ToStr(regDelta - 17) + " tr\n");
940 			PutStream(regCross);
941 			PutStream("gr\n");
942 			PutStream("gs\n");
943 			PutStream(ToStr(regDelta - 17) + " " + ToStr(maxBoxY / 2.0 - 7.0) + " tr\n");
944 			PutStream(regCross);
945 			PutStream("gr\n");
946 			PutStream("gs\n");
947 			PutStream(ToStr(maxBoxX / 2.0 - 7.0) + " " + ToStr(maxBoxY - regDelta + 3.0) + " tr\n");
948 			PutStream(regCross);
949 			PutStream("gr\n");
950 			PutStream("gs\n");
951 			PutStream(ToStr(maxBoxX - regDelta + 3.0) + " " + ToStr(maxBoxY / 2.0 - 7.0) + " tr\n");
952 			PutStream(regCross);
953 			PutStream("gr\n");
954 		}
955 		if (Options.colorMarks)
956 		{
957 			double startX = markOffs + bleedLeft + 6.0;
958 			double startY = maxBoxY - markOffs + Options.markOffset + 2.0;
959 			PutStream("0 0 0 1 cmyk\n");
960 			double col = 1.0;
961 			for (int bl = 0; bl < 11; bl++)
962 			{
963 				PutStream("0 0 0 " + ToStr(col) + " cmyk\n");
964 				PutStream(ToStr(startX + bl * 14.0) + " " + ToStr(startY) + " 14 14 rectfill\n");
965 				PutStream("0 0 0 1 cmyk\n");
966 				PutStream(ToStr(startX + bl * 14.0) + " " + ToStr(startY) + " 14 14 rectstroke\n");
967 				col -= 0.1;
968 			}
969 			startX = maxBoxX - bleedRight - markOffs - 20.0;
970 			PutStream("0 0 0 0.5 cmyk\n");
971 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
972 			PutStream("0 0 0 1 cmyk\n");
973 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
974 			startX -= 14.0;
975 			PutStream("0 0 0.5 0 cmyk\n");
976 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
977 			PutStream("0 0 0 1 cmyk\n");
978 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
979 			startX -= 14.0;
980 			PutStream("0 0.5 0 0 cmyk\n");
981 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
982 			PutStream("0 0 0 1 cmyk\n");
983 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
984 			startX -= 14.0;
985 			PutStream("0.5 0 0 0 cmyk\n");
986 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
987 			PutStream("0 0 0 1 cmyk\n");
988 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
989 			startX -= 14.0;
990 			PutStream("1 1 0 0 cmyk\n");
991 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
992 			PutStream("0 0 0 1 cmyk\n");
993 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
994 			startX -= 14.0;
995 			PutStream("1 0 1 0 cmyk\n");
996 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
997 			PutStream("0 0 0 1 cmyk\n");
998 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
999 			startX -= 14.0;
1000 			PutStream("0 1 1 0 cmyk\n");
1001 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
1002 			PutStream("0 0 0 1 cmyk\n");
1003 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
1004 			startX -= 14.0;
1005 			PutStream("0 0 0 1 cmyk\n");
1006 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
1007 			PutStream("0 0 0 1 cmyk\n");
1008 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
1009 			startX -= 14.0;
1010 			PutStream("0 0 1 0 cmyk\n");
1011 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
1012 			PutStream("0 0 0 1 cmyk\n");
1013 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
1014 			startX -= 14.0;
1015 			PutStream("0 1 0 0 cmyk\n");
1016 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
1017 			PutStream("0 0 0 1 cmyk\n");
1018 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
1019 			startX -= 14.0;
1020 			PutStream("1 0 0 0 cmyk\n");
1021 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectfill\n");
1022 			PutStream("0 0 0 1 cmyk\n");
1023 			PutStream(ToStr(startX) + " " + ToStr(startY) + " 14 14 rectstroke\n");
1024 		}
1025 		PutStream("gr\n");
1026 	}
1027 	PutStream("gr\n");
1028 	PutStream("sp\n");
1029 	PutStream("end\n");
1030 }
1031 
PS_curve(double x1,double y1,double x2,double y2,double x3,double y3)1032 void PSLib::PS_curve(double x1, double y1, double x2, double y2, double x3, double y3)
1033 {
1034 	PutStream(ToStr(x1) + " " + ToStr(y1) + " " + ToStr(x2) + " " + ToStr(y2) + " " + ToStr(x3) + " " + ToStr(y3) + " cu\n");
1035 }
1036 
PS_moveto(double x,double y)1037 void PSLib::PS_moveto(double x, double y)
1038 {
1039 	PutStream(ToStr(x) + " " + ToStr(y) + " m\n");
1040 }
1041 
PS_lineto(double x,double y)1042 void PSLib::PS_lineto(double x, double y)
1043 {
1044 	PutStream(ToStr(x) + " " + ToStr(y) + " li\n");
1045 }
1046 
PS_closepath()1047 void PSLib::PS_closepath()
1048 {
1049 	PutStream("cl\n");
1050 }
1051 
PS_translate(double x,double y)1052 void PSLib::PS_translate(double x, double y)
1053 {
1054 	PutStream(ToStr(x) + " " + ToStr(y) + " tr\n");
1055 }
1056 
PS_scale(double x,double y)1057 void PSLib::PS_scale(double x, double y)
1058 {
1059 	PutStream(ToStr(x) + " " + ToStr(y) + " sc\n");
1060 }
1061 
PS_rotate(double x)1062 void PSLib::PS_rotate(double x)
1063 {
1064 	PutStream(ToStr(x) + " ro\n");
1065 }
1066 
PS_clip(bool mu)1067 void PSLib::PS_clip(bool mu)
1068 {
1069 	PutStream(mu ? "eoclip newpath\n" : "clip newpath\n");
1070 }
1071 
PS_save()1072 void PSLib::PS_save()
1073 {
1074 	PutStream("gs\n");
1075 }
1076 
PS_restore()1077 void PSLib::PS_restore()
1078 {
1079 	PutStream("gr\n");
1080 }
1081 
PS_setcmykcolor_fill(double c,double m,double y,double k)1082 void PSLib::PS_setcmykcolor_fill(double c, double m, double y, double k)
1083 {
1084 	FillColor = ToStr(c) + " " + ToStr(m) + " " + ToStr(y) + " " + ToStr(k);
1085 }
1086 
PS_setcmykcolor_dummy()1087 void PSLib::PS_setcmykcolor_dummy()
1088 {
1089 	PutStream("0 0 0 0 cmyk\n");
1090 }
1091 
PS_setcmykcolor_stroke(double c,double m,double y,double k)1092 void PSLib::PS_setcmykcolor_stroke(double c, double m, double y, double k)
1093 {
1094 	StrokeColor = ToStr(c) + " " + ToStr(m) + " " + ToStr(y) + " " + ToStr(k);
1095 }
1096 
PS_setlinewidth(double w)1097 void PSLib::PS_setlinewidth(double w)
1098 {
1099 	PutStream(ToStr(w) + " sw\n");
1100 	LineW = w;
1101 }
1102 
PS_setdash(Qt::PenStyle st,double offset,QVector<double> dash)1103 void PSLib::PS_setdash(Qt::PenStyle st, double offset, QVector<double> dash)
1104 {
1105 	if (dash.count() != 0)
1106 	{
1107 		PutStream("[ ");
1108 		QVector<double>::iterator it;
1109 		for ( it = dash.begin(); it != dash.end(); ++it )
1110 		{
1111 			PutStream(ToStr(*it) + " ");
1112 		}
1113 		PutStream("] " + ToStr(offset) + " setdash\n");
1114 	}
1115 	else
1116 		PutStream("[" + getDashString(st, LineW) + "] 0 setdash\n");
1117 }
1118 
PS_setcapjoin(Qt::PenCapStyle ca,Qt::PenJoinStyle jo)1119 void PSLib::PS_setcapjoin(Qt::PenCapStyle ca, Qt::PenJoinStyle jo)
1120 {
1121 	switch (ca)
1122 		{
1123 		case Qt::FlatCap:
1124 			PutStream("0 setlinecap\n");
1125 			break;
1126 		case Qt::SquareCap:
1127 			PutStream("2 setlinecap\n");
1128 			break;
1129 		case Qt::RoundCap:
1130 			PutStream("1 setlinecap\n");
1131 			break;
1132 		default:
1133 			PutStream("0 setlinecap\n");
1134 			break;
1135 		}
1136 	switch (jo)
1137 		{
1138 		case Qt::MiterJoin:
1139 			PutStream("0 setlinejoin\n");
1140 			break;
1141 		case Qt::BevelJoin:
1142 			PutStream("2 setlinejoin\n");
1143 			break;
1144 		case Qt::RoundJoin:
1145 			PutStream("1 setlinejoin\n");
1146 			break;
1147 		default:
1148 			PutStream("0 setlinejoin\n");
1149 			break;
1150 		}
1151 }
1152 
PS_fill()1153 void PSLib::PS_fill()
1154 {
1155 	if (fillRule)
1156 		PutStream(FillColor + " cmyk eofill\n");
1157 	else
1158 		PutStream(FillColor + " cmyk fill\n");
1159 }
1160 
PS_fillspot(const QString & color,double shade)1161 void PSLib::PS_fillspot(const QString& color, double shade)
1162 {
1163 	if (fillRule)
1164 		PutStream(ToStr(shade / 100.0) + " " + spotMap[color] + " eofill\n");
1165 	else
1166 		PutStream(ToStr(shade / 100.0) + " " + spotMap[color] + " fill\n");
1167 }
1168 
PS_strokespot(const QString & color,double shade)1169 void PSLib::PS_strokespot(const QString& color, double shade)
1170 {
1171 	PutStream(ToStr(shade / 100.0) + " " + spotMap[color] + " st\n");
1172 }
1173 
PS_stroke()1174 void PSLib::PS_stroke()
1175 {
1176 	PutStream(StrokeColor + " cmyk st\n");
1177 }
1178 
PS_fill_stroke()1179 void PSLib::PS_fill_stroke()
1180 {
1181 	PS_save();
1182 	PS_fill();
1183 	PS_restore();
1184 	PS_stroke();
1185 }
1186 
PS_newpath()1187 void PSLib::PS_newpath()
1188 {
1189 	PutStream("newpath\n");
1190 }
1191 
PS_show(double x,double y)1192 void PSLib::PS_show(double x, double y)
1193 {
1194 	PS_moveto(x, y);
1195 	PutStream("/hyphen glyphshow\n");
1196 }
1197 
PS_showSub(uint chr,const QString & font,double size,bool stroke)1198 void PSLib::PS_showSub(uint chr, const QString& font, double size, bool stroke)
1199 {
1200 	PutStream(" (G" + IToStr(chr) + ") " + font + " " + ToStr(size / 10.0) + " ");
1201 	PutStream(stroke ? "shgs\n" : "shgf\n");
1202 }
1203 
PS_ImageData(PageItem * item,const QString & fn,const QString & Name,const QString & Prof,bool UseEmbedded)1204 bool PSLib::PS_ImageData(PageItem *item, const QString& fn, const QString& Name, const QString& Prof, bool UseEmbedded)
1205 {
1206 	bool dummy;
1207 	QByteArray tmp;
1208 	QFileInfo fi = QFileInfo(fn);
1209 	QString ext = fi.suffix().toLower();
1210 	if (ext.isEmpty())
1211 		ext = getImageType(fn);
1212 	if (extensionIndicatesEPS(ext) && (item->pixm.imgInfo.type != ImageType7))
1213 	{
1214 		if (loadRawText(fn, tmp))
1215 		{
1216 			PutStream("currentfile 1 (%ENDEPSDATA) /SubFileDecode filter /ReusableStreamDecode filter\n");
1217 			PutStream("%%BeginDocument: " + fi.fileName() + "\n");
1218 			if (getDouble(tmp.mid(0, 4), true) == 0xC5D0D3C6)
1219 			{
1220 				char* data = tmp.data();
1221 				uint startPos = getDouble(tmp.mid(4, 4), false);
1222 				uint length = getDouble(tmp.mid(8, 4), false);
1223 				PutStream(data+startPos, length, false);
1224 			}
1225 			else
1226 				PutStream(tmp, false);
1227 			PutStream("\n%ENDEPSDATA\n");
1228 			PutStream("%%EndDocument\n");
1229 			PutStream("/" + PSEncode(Name) + "Bild exch def\n");
1230 			return true;
1231 		}
1232 		return false;
1233 	}
1234 	ScImage image;
1235 	QByteArray imgArray;
1236 	image.imgInfo.valid = false;
1237 	image.imgInfo.clipPath = "";
1238 	image.imgInfo.PDSpathData.clear();
1239 	image.imgInfo.layerInfo.clear();
1240 	image.imgInfo.RequestProps = item->pixm.imgInfo.RequestProps;
1241 	image.imgInfo.isRequest = item->pixm.imgInfo.isRequest;
1242 	CMSettings cms(item->doc(), Prof, item->ImageIntent);
1243 	cms.allowColorManagement(true);
1244 	cms.setUseEmbeddedProfile(UseEmbedded);
1245 	if (!image.loadPicture(fn, item->pixm.imgInfo.actualPageNumber, cms, ScImage::CMYKData, 300, &dummy))
1246 	{
1247 		PS_Error_ImageLoadFailure(fn);
1248 		return false;
1249 	}
1250 	image.applyEffect(item->effectsInUse, colorsToUse, true);
1251 	QByteArray maskArray;
1252 	if (item->pixm.imgInfo.type != ImageType7)
1253 	{
1254 		bool alphaLoaded = image.getAlpha(fn, item->pixm.imgInfo.actualPageNumber, maskArray, false, true, 300);
1255 		if (!alphaLoaded)
1256 		{
1257 			PS_Error_MaskLoadFailure(fn);
1258 			return false;
1259 		}
1260 	}
1261 	if ((maskArray.size() > 0) && (item->pixm.imgInfo.type != ImageType7))
1262 	{
1263 		PutStream("currentfile /ASCII85Decode filter /FlateDecode filter /ReusableStreamDecode filter\n");
1264 		if (!PutImageToStream(image, maskArray, -1))
1265 		{
1266 			PS_Error_ImageDataWriteFailure();
1267 			return false;
1268 		}
1269 		PutStream("/" + PSEncode(Name) + "Bild exch def\n");
1270 	}
1271 	else
1272 	{
1273 		PutStream("currentfile /ASCII85Decode filter /FlateDecode filter /ReusableStreamDecode filter\n");
1274 		if (!PutImageToStream(image, -1))
1275 		{
1276 			PS_Error_ImageDataWriteFailure();
1277 			return false;
1278 		}
1279 		PutStream("/" + PSEncode(Name) + "Bild exch def\n");
1280 		imgArray.resize(0);
1281 	}
1282 	return true;
1283 }
1284 
PS_image(PageItem * item,double x,double y,const QString & fn,double scalex,double scaley,const QString & Prof,bool UseEmbedded,const QString & Name)1285 bool PSLib::PS_image(PageItem *item, double x, double y, const QString& fn, double scalex, double scaley, const QString& Prof, bool UseEmbedded, const QString& Name)
1286 {
1287 	bool dummy;
1288 	QByteArray tmp;
1289 
1290 	QFileInfo fi = QFileInfo(fn);
1291 	QString ext = fi.suffix().toLower();
1292 	if (ext.isEmpty())
1293 		ext = getImageType(fn);
1294 	if (extensionIndicatesEPS(ext) && (item->pixm.imgInfo.type != ImageType7))
1295 	{
1296 		if (loadRawText(fn, tmp))
1297 		{
1298 			PutStream("bEPS\n");
1299 			PutStream(ToStr(PrefsManager::instance().appPrefs.extToolPrefs.gs_Resolution / 72.0 * scalex) + " " + ToStr(PrefsManager::instance().appPrefs.extToolPrefs.gs_Resolution / 72.0 * scaley) + " sc\n");
1300 			PutStream(ToStr(-item->BBoxX+x * scalex) + " " + ToStr(y * scalex) + " tr\n");
1301 			int h = item->pixm.height();
1302 			PutStream("0 " + ToStr(h*scaley) + " tr\n");
1303 			PutStream(ToStr(-item->imageRotation()) + " ro\n");
1304 			PutStream("0 " + ToStr(-h*scaley) + " tr\n");
1305 			if (!Name.isEmpty())
1306 			{
1307 				PutStream(PSEncode(Name) + "Bild cvx exec\n");
1308 				PutStream(PSEncode(Name) + "Bild resetfile\n");
1309 			}
1310 			else
1311 			{
1312 				PutStream("%%BeginDocument: " + fi.fileName() + "\n");
1313 				if (getDouble(tmp.mid(0, 4), true) == 0xC5D0D3C6)
1314 				{
1315 					char* data = tmp.data();
1316 					uint startPos = getDouble(tmp.mid(4, 4), false);
1317 					uint length = getDouble(tmp.mid(8, 4), false);
1318 					PutStream(data+startPos, length, false);
1319 				}
1320 				else
1321 					PutStream(tmp);
1322 				PutStream("\n%%EndDocument\n");
1323 			}
1324 			PutStream("eEPS\n");
1325 			return true;
1326 		}
1327 		return false;
1328 	}
1329 
1330 	ScImage image;
1331 	image.imgInfo.valid = false;
1332 	image.imgInfo.clipPath = "";
1333 	image.imgInfo.PDSpathData.clear();
1334 	image.imgInfo.layerInfo.clear();
1335 	image.imgInfo.RequestProps = item->pixm.imgInfo.RequestProps;
1336 	image.imgInfo.isRequest = item->pixm.imgInfo.isRequest;
1337 	CMSettings cms(item->doc(), Prof, item->ImageIntent);
1338 	cms.allowColorManagement(true);
1339 	cms.setUseEmbeddedProfile(UseEmbedded);
1340 	int resolution = 300;
1341 	if (item->isLatexFrame())
1342 		resolution = item->asLatexFrame()->realDpi();
1343 	else if (item->pixm.imgInfo.type == ImageType7)
1344 		resolution = 72;
1345 	//	int resolution = (item->pixm.imgInfo.type == ImageType7) ? 72 : 300;
1346 	if ( !image.loadPicture(fn, item->pixm.imgInfo.actualPageNumber, cms, ScImage::CMYKData, resolution, &dummy) )
1347 	{
1348 		PS_Error_ImageLoadFailure(fn);
1349 		return false;
1350 	}
1351 	image.applyEffect(item->effectsInUse, colorsToUse, true);
1352 	int w = image.width();
1353 	int h = image.height();
1354 	PutStream(ToStr(x*scalex) + " " + ToStr(y*scaley) + " tr\n");
1355 	PutStream("0 " + ToStr(h*scaley) + " tr\n");
1356 	PutStream(ToStr(-item->imageRotation()) + " ro\n");
1357 	PutStream("0 " + ToStr(-h*scaley) + " tr\n");
1358 	if ((extensionIndicatesPDF(ext)) && (!item->isLatexFrame()))
1359 	{
1360 		scalex *= PrefsManager::instance().appPrefs.extToolPrefs.gs_Resolution / 300.0;
1361 		scaley *= PrefsManager::instance().appPrefs.extToolPrefs.gs_Resolution / 300.0;
1362 	}
1363 	//	PutStream(ToStr(x*scalex) + " " + ToStr(y*scaley) + " tr\n");
1364 	PutStream(ToStr(qRound(scalex*w)) + " " + ToStr(qRound(scaley*h)) + " sc\n");
1365 	PutStream(((!DoSep) && (!GraySc)) ? "/DeviceCMYK setcolorspace\n" : "/DeviceGray setcolorspace\n");
1366 	QByteArray maskArray;
1367 	ScImage img2;
1368 	img2.imgInfo.clipPath = "";
1369 	img2.imgInfo.PDSpathData.clear();
1370 	img2.imgInfo.layerInfo.clear();
1371 	img2.imgInfo.RequestProps = item->pixm.imgInfo.RequestProps;
1372 	img2.imgInfo.isRequest = item->pixm.imgInfo.isRequest;
1373 	if (item->pixm.imgInfo.type != ImageType7)
1374 	{
1375 		bool alphaLoaded = img2.getAlpha(fn, item->pixm.imgInfo.actualPageNumber, maskArray, false, true, resolution);
1376 		if (!alphaLoaded)
1377 		{
1378 			PS_Error_MaskLoadFailure(fn);
1379 			return false;
1380 		}
1381 	}
1382 	if ((maskArray.size() > 0) && (item->pixm.imgInfo.type != ImageType7))
1383 	{
1384 		int plate = DoSep ? Plate : (GraySc ? -2 : -1);
1385 		// JG - Experimental code using Type3 image instead of patterns
1386 		PutStream("<< /ImageType 3\n");
1387 		PutStream("   /DataDict <<\n");
1388 		PutStream("      /ImageType 1\n");
1389 		PutStream("      /Width  " + IToStr(w) + "\n");
1390 		PutStream("      /Height " + IToStr(h) + "\n");
1391 		PutStream("      /BitsPerComponent 8\n");
1392 		PutStream( (GraySc || DoSep) ? "      /Decode [1 0]\n" : "      /Decode [0 1 0 1 0 1 0 1]\n");
1393 		PutStream("      /ImageMatrix [" + IToStr(w) + " 0 0 " + IToStr(-h) + " 0 " + IToStr(h) + "]\n");
1394 		if (Name.length() > 0)
1395 			PutStream("      /DataSource " + PSEncode(Name) + "Bild\n");
1396 		else
1397 			PutStream("      /DataSource currentfile /ASCII85Decode filter /FlateDecode filter\n");
1398 		PutStream("      >>\n");
1399 		PutStream("   /MaskDict <<\n");
1400 		PutStream("      /ImageType 1\n");
1401 		PutStream("      /Width  " + IToStr(w) + "\n");
1402 		PutStream("      /Height " + IToStr(h) + "\n");
1403 		PutStream("      /BitsPerComponent 8\n");
1404 		PutStream("      /Decode [1 0]\n");
1405 		PutStream("      /ImageMatrix [" + IToStr(w) + " 0 0 " + IToStr(-h) + " 0 " + IToStr(h) + "]\n");
1406 		PutStream("      >>\n");
1407 		PutStream("   /InterleaveType 1\n");
1408 		PutStream(">>\n");
1409 		PutStream("image\n");
1410 		if (Name.isEmpty())
1411 		{
1412 			if (!PutImageToStream(image, maskArray, plate))
1413 			{
1414 				PS_Error_ImageDataWriteFailure();
1415 				return false;
1416 			}
1417 		}
1418 		else
1419 		{
1420 			PutStream(PSEncode(Name) + "Bild resetfile\n");
1421 			//PutStream(PSEncode(Name) + "Mask resetfile\n");
1422 		}
1423 	}
1424 	else
1425 	{
1426 		PutStream("<< /ImageType 1\n");
1427 		PutStream("   /Width " + IToStr(w) + "\n");
1428 		PutStream("   /Height " + IToStr(h) + "\n");
1429 		PutStream("   /BitsPerComponent 8\n");
1430 		if (DoSep)
1431 			PutStream("   /Decode [1 0]\n");
1432 		else
1433 			PutStream( GraySc ? "   /Decode [1 0]\n" : "   /Decode [0 1 0 1 0 1 0 1]\n");
1434 		PutStream("   /ImageMatrix [" + IToStr(w) + " 0 0 " + IToStr(-h) + " 0 " + IToStr(h) + "]\n");
1435 		if (!Name.isEmpty())
1436 		{
1437 			PutStream("   /DataSource " + PSEncode(Name) + "Bild >>\n");
1438 			PutStream("image\n");
1439 			PutStream(PSEncode(Name) + "Bild resetfile\n");
1440 		}
1441 		else
1442 		{
1443 			int plate = DoSep ? Plate : (GraySc ? -2 : -1);
1444 			PutStream("   /DataSource currentfile /ASCII85Decode filter /FlateDecode filter >>\n");
1445 			PutStream("image\n");
1446 			if (!PutImageToStream(image, plate))
1447 			{
1448 				PS_Error_ImageDataWriteFailure();
1449 				return false;
1450 			}
1451 		}
1452 	}
1453 	return true;
1454 }
1455 
1456 
PS_plate(int nr,const QString & name)1457 void PSLib::PS_plate(int nr, const QString& name)
1458 {
1459 	switch (nr)
1460 	{
1461 		case 0:
1462 			PutStream("%%PlateColor Black\n");
1463 			PutStream("/setcmykcolor {exch pop exch pop exch pop 1 exch sub oldsetgray} bind def\n");
1464 			PutStream("/setrgbcolor {pop pop pop 1 oldsetgray} bind def\n");
1465 			break;
1466 		case 1:
1467 			PutStream("%%PlateColor Cyan\n");
1468 			PutStream("/setcmykcolor {pop pop pop 1 exch sub oldsetgray} bind def\n");
1469 			PutStream("/setrgbcolor {pop pop oldsetgray} bind def\n");
1470 			break;
1471 		case 2:
1472 			PutStream("%%PlateColor Magenta\n");
1473 			PutStream("/setcmykcolor {pop pop exch pop 1 exch sub oldsetgray} bind def\n");
1474 			PutStream("/setrgbcolor {pop exch pop oldsetgray} bind def\n");
1475 			break;
1476 		case 3:
1477 			PutStream("%%PlateColor Yellow\n");
1478 			PutStream("/setcmykcolor {pop exch pop exch pop 1 exch sub oldsetgray} bind def\n");
1479 			PutStream("/setrgbcolor {exch pop exch pop oldsetgray} bind def\n");
1480 			break;
1481 		default:
1482 			PutStream("%%PlateColor " + name + "\n");
1483 			PutStream("/setcmykcolor {exch 0.11 mul add exch 0.59 mul add exch 0.3 mul add dup 1 gt {pop 1} if 1 exch sub oldsetgray} bind def\n");
1484 			PutStream("/setrgbcolor {0.11 mul exch 0.59 mul add exch 0.3 mul add oldsetgray} bind def\n");
1485 			break;
1486 	}
1487 	Plate = nr;
1488 	currentSpot = name;
1489 	DoSep = true;
1490 }
1491 
PS_setGray()1492 void PSLib::PS_setGray()
1493 {
1494 	GraySc = true;
1495 }
1496 
PDF_Bookmark(const QString & text,uint Seite)1497 void PSLib::PDF_Bookmark(const QString& text, uint Seite)
1498 {
1499 	PutStream("[/Title (" + text + ") /Page " + IToStr(Seite) + " /View [/Fit]\n");
1500 	PutStream("/OUT pdfmark\n");
1501 }
1502 
PDF_Annotation(PageItem * item,const QString & text,double x,double y,double b,double h)1503 void PSLib::PDF_Annotation(PageItem *item, const QString& text, double x, double y, double b, double h)
1504 {
1505 	PutStream("[\n/Rect [ " + ToStr(x) + " " + ToStr(y)  + " " + ToStr(b) + " " + ToStr(h) + " ]\n");
1506 	switch (item->annotation().Type())
1507 	{
1508 		case 0:
1509 		case Annotation::Text:
1510 			PutStream("/Subtype /Text\n");
1511 			PutStream("/Contents (" + text + ")\n/Open false\n");
1512 			break;
1513 		case 1:
1514 		case Annotation::Link:
1515 			PutStream("/Subtype /Link\n");
1516 			if (item->annotation().ActionType() == Annotation::Action_GoTo)
1517 			{
1518 				PutStream("/Page " + QString::number(item->annotation().Ziel() + 1) + "\n");
1519 				PutStream("/View [ /XYZ " + item->annotation().Action() + "]\n");
1520 			}
1521 			if (item->annotation().ActionType() == Annotation::Action_GoToR_FileRel)
1522 			{
1523 				QFileInfo fiBase(Spool.fileName());
1524 				QString baseDir = fiBase.absolutePath();
1525 				PutStream("/Action /GoToR\n");
1526 				PutStream("/File (" + Path2Relative(item->annotation().Extern(), baseDir) + ")\n");
1527 				PutStream("/Page " + QString::number(item->annotation().Ziel() + 1) + "\n");
1528 				PutStream("/View [ /XYZ " + item->annotation().Action() + "]\n");
1529 			}
1530 			if (item->annotation().ActionType() == Annotation::Action_URI)
1531 			{
1532 			/* The PDFMark docs say that for URI actions should contain an entry /Subtype /URI
1533 			   but tests with Ghostscript shows that only /S /URI works. Don't know if that is
1534 			   an error in the docs or a bug in Ghostscript
1535 				PutStream("/Action << /Subtype /URI /URI (" + item->annotation().Extern() + ") >>\n");
1536 			*/
1537 				PutStream("/Action << /S /URI /URI (" + item->annotation().Extern() + ") >>\n");
1538 			}
1539 			if (item->annotation().ActionType() == Annotation::Action_GoToR_FileAbs)
1540 			{
1541 				PutStream("/Action /GoToR\n");
1542 				PutStream("/File (" + item->annotation().Extern() + ")\n");
1543 				PutStream("/Page " + QString::number(item->annotation().Ziel() + 1) + "\n");
1544 				PutStream("/View [ /XYZ " + item->annotation().Action() + "]\n");
1545 			}
1546 			break;
1547 		default:
1548 			break;
1549 	}
1550 	if ((item->annotation().Type() < 2) || (item->annotation().Type() > 9))
1551 		PutStream("/Border [ 0 0 0 ]\n");
1552 	PutStream("/Title (" + item->itemName().replace(".", "_" ) + ")\n");
1553 	PutStream("/ANN pdfmark\n");
1554 }
1555 
1556 
PS_close()1557 void PSLib::PS_close()
1558 {
1559 	PutStream("%%Trailer\n");
1560 //	PutStream("end\n");
1561 	PutStream("%%EOF\n");
1562 	Spool.close();
1563 }
1564 
PS_insert(const QString & i)1565 void PSLib::PS_insert(const QString& i)
1566 {
1567 	PutStream(i);
1568 }
1569 
PS_Error(const QString & message)1570 void PSLib::PS_Error(const QString& message)
1571 {
1572 	ErrorMessage = message;
1573 	if (!ScCore->usingGUI())
1574 		qDebug("%s", message.toLocal8Bit().data());
1575 }
1576 
PS_Error_ImageDataWriteFailure()1577 void PSLib::PS_Error_ImageDataWriteFailure()
1578 {
1579 	PS_Error( tr("Failed to write data for an image"));
1580 }
1581 
PS_Error_ImageLoadFailure(const QString & fileName)1582 void PSLib::PS_Error_ImageLoadFailure(const QString& fileName)
1583 {
1584 	PS_Error( tr("Failed to load an image : %1").arg(fileName) );
1585 }
1586 
PS_Error_MaskLoadFailure(const QString & fileName)1587 void PSLib::PS_Error_MaskLoadFailure(const QString& fileName)
1588 {
1589 	PS_Error( tr("Failed to load an image mask : %1").arg(fileName) );
1590 }
1591 
PS_Error_InsufficientMemory()1592 void PSLib::PS_Error_InsufficientMemory()
1593 {
1594 	PS_Error( tr("Insufficient memory for processing an image"));
1595 }
1596 
createPS(const QString & outputFileName)1597 int PSLib::createPS(const QString& outputFileName)
1598 {
1599 	bool errorOccured = false;
1600 
1601 	if (!PS_set_file(outputFileName))
1602 		return 1;
1603 
1604 	std::vector<int> &pageNs = Options.pageNumbers;
1605 	bool outputSep = Options.outputSeparations;
1606 	QString separationName = Options.separationName;
1607 	QStringList separations = Options.allSeparations;
1608 	bool Hm = Options.mirrorH;
1609 	bool Vm = Options.mirrorV;
1610 	bool doClip = Options.doClip;
1611 	int sepac;
1612 	int pagemult;
1613 	if ((outputSep) && (separationName == "All"))
1614 		pagemult = separations.count();
1615 	else
1616 		pagemult = 1;
1617 //	QVector<double> dum;
1618 	double gx = 0.0;
1619 	double gy = 0.0;
1620 	double gw = 0.0;
1621 	double gh = 0.0;
1622 	PS_set_Info("Author", m_Doc->documentInfo().author());
1623 	PS_set_Info("Title", m_Doc->documentInfo().title());
1624 	if (!Options.useColor)
1625 		PS_setGray();
1626 	if ((m_Doc->HasCMS) && (ScCore->haveCMS()))
1627 		solidTransform = m_Doc->colorEngine.createTransform(m_Doc->DocInputCMYKProf, Format_CMYK_16, m_Doc->DocPrinterProf, Format_CMYK_16, m_Doc->IntentColors, 0);
1628 	else
1629 		solidTransform = ScColorTransform();
1630 	if (ScCore->usingGUI())
1631 	{
1632 		QString title = QObject::tr("Exporting PostScript File");
1633 		if (m_outputFormat == OutputPS)
1634 			title = QObject::tr("Printing File");
1635 		progressDialog = new MultiProgressDialog(title, CommonStrings::tr_Cancel, m_Doc->scMW());
1636 		if (progressDialog)
1637 		{
1638 			QStringList barNames, barTexts;
1639 			barNames << "EMP" << "EP";
1640 			barTexts << tr("Processing Master Page:") << tr("Exporting Page:");
1641 			QList<bool> barsNumeric;
1642 			barsNumeric << true << true;
1643 			progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
1644 			progressDialog->setOverallTotalSteps(pageNs.size()+m_Doc->MasterPages.count());
1645 			progressDialog->setTotalSteps("EMP", m_Doc->MasterPages.count());
1646 			progressDialog->setTotalSteps("EP", pageNs.size());
1647 			progressDialog->setOverallProgress(0);
1648 			progressDialog->setProgress("EMP", 0);
1649 			progressDialog->setProgress("EP", 0);
1650 			progressDialog->show();
1651 			connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
1652 			ScQApp->processEvents();
1653 		}
1654 	}
1655 	uint docSelectionCount = m_Doc->m_Selection->count();
1656 	if ((m_outputFormat == OutputEPS) && (docSelectionCount != 0))
1657 	{
1658 		double minx =  std::numeric_limits<double>::max();
1659 		double miny =  std::numeric_limits<double>::max();
1660 		double maxx = -std::numeric_limits<double>::max();
1661 		double maxy = -std::numeric_limits<double>::max();
1662 		for (uint ep = 0; ep < docSelectionCount; ++ep)
1663 		{
1664 			PageItem* currItem = m_Doc->m_Selection->itemAt(ep);
1665 			double lw = currItem->lineWidth() / 2.0;
1666 			if (currItem->rotation() != 0)
1667 			{
1668 				FPointArray pb;
1669 				pb.resize(0);
1670 				pb.addPoint(FPoint(currItem->xPos() - lw, currItem->yPos() - lw));
1671 				pb.addPoint(FPoint(currItem->width() + lw * 2.0, -lw, currItem->xPos() - lw, currItem->yPos() - lw, currItem->rotation(), 1.0, 1.0));
1672 				pb.addPoint(FPoint(currItem->width() + lw * 2.0, currItem->height() + lw * 2.0, currItem->xPos() - lw, currItem->yPos() - lw, currItem->rotation(), 1.0, 1.0));
1673 				pb.addPoint(FPoint(-lw, currItem->height() + lw * 2.0, currItem->xPos() - lw, currItem->yPos() - lw, currItem->rotation(), 1.0, 1.0));
1674 				for (uint pc = 0; pc < 4; ++pc)
1675 				{
1676 					minx = qMin(minx, pb.point(pc).x());
1677 					miny = qMin(miny, pb.point(pc).y());
1678 					maxx = qMax(maxx, pb.point(pc).x());
1679 					maxy = qMax(maxy, pb.point(pc).y());
1680 				}
1681 			}
1682 			else
1683 			{
1684 				minx = qMin(minx, currItem->xPos() - lw);
1685 				miny = qMin(miny, currItem->yPos() - lw);
1686 				maxx = qMax(maxx, currItem->xPos() - lw + currItem->width() + lw * 2.0);
1687 				maxy = qMax(maxy, currItem->yPos() - lw + currItem->height()+ lw * 2.0);
1688 			}
1689 		}
1690 		gx = minx;
1691 		gy = miny;
1692 		gw = maxx - minx;
1693 		gh = maxy - miny;
1694 		int pgNum = pageNs[0] - 1;
1695 		gx -= m_Doc->Pages->at(pgNum)->xOffset();
1696 		gy -= m_Doc->Pages->at(pgNum)->yOffset();
1697 		errorOccured = !PS_begin_doc(gx, m_Doc->pageHeight() - (gy + gh), gx + gw, m_Doc->pageHeight() - gy, 1 * pagemult);
1698 	}
1699 	else
1700 	{
1701 		double maxWidth = 0.0;
1702 		double maxHeight = 0.0;
1703 		for (size_t i = 0; i < pageNs.size(); ++i)
1704 		{
1705 			int pgNum = pageNs[i] - 1;
1706 			maxWidth = qMax(m_Doc->Pages->at(pgNum)->width(), maxWidth);
1707 			maxHeight = qMax(m_Doc->Pages->at(pgNum)->height(), maxHeight);
1708 		}
1709 		errorOccured = !PS_begin_doc(0.0, 0.0, maxWidth, maxHeight, pageNs.size() * pagemult);
1710 	}
1711 
1712 	sepac = 0;
1713 	uint aa = 0;
1714 	uint a;
1715 	while (aa < pageNs.size() && !abortExport && !errorOccured)
1716 	{
1717 		if (progressDialog)
1718 		{
1719 			progressDialog->setProgress("EP", aa);
1720 			progressDialog->setOverallProgress(aa + m_Doc->MasterPages.count());
1721 			ScQApp->processEvents();
1722 		}
1723 		a = pageNs[aa]-1;
1724 		ScPage* page = m_Doc->Pages->at(a);
1725 		if ((m_outputFormat == OutputEPS) && (m_Doc->m_Selection->count() != 0))
1726 		{
1727 			MarginStruct Ma;
1728 			Ma.setLeft(gx);
1729 			Ma.setTop(gy);
1730 			Ma.setBottom(page->height() - (gy + gh));
1731 			Ma.setRight(page->width() - (gx + gw));
1732 			PS_begin_page(page, &Ma, true);
1733 		}
1734 		else
1735 			PS_begin_page(page, &page->Margins, doClip);
1736 		if (Hm)
1737 		{
1738 			PS_translate(page->width(), 0);
1739 			PS_scale(-1, 1);
1740 		}
1741 		if (Vm)
1742 		{
1743 			PS_translate(0, page->height());
1744 			PS_scale(1, -1);
1745 		}
1746 		if (outputSep)
1747 		{
1748 			if (separationName == "Black")
1749 				PS_plate(0);
1750 			else if (separationName == "Cyan")
1751 				PS_plate(1);
1752 			else if (separationName == "Magenta")
1753 				PS_plate(2);
1754 			else if (separationName == "Yellow")
1755 				PS_plate(3);
1756 			else if (separationName == "All")
1757 				PS_plate(sepac, separations[sepac]);
1758 			else
1759 				PS_plate(4, separationName);
1760 		}
1761 		ScLayer ll;
1762 		ll.isPrintable = false;
1763 		for (int lam = 0; lam < m_Doc->Layers.count() && !abortExport && !errorOccured; ++lam)
1764 		{
1765 			m_Doc->Layers.levelToLayer(ll, lam);
1766 			if (!ll.isPrintable)
1767 				continue;
1768 			if (!page->masterPageNameEmpty() && !abortExport && !errorOccured)
1769 			{
1770 				errorOccured |= !ProcessMasterPageLayer(page, ll, a + 1);
1771 			}
1772 			if (!abortExport && !errorOccured)
1773 			{
1774 				errorOccured |= !ProcessPageLayer(page, ll, a + 1);
1775 			}
1776 		}
1777 		if (!abortExport && !errorOccured)
1778 			PS_end_page();
1779 		if (outputSep)
1780 		{
1781 			if (separationName != "All")
1782 				aa++;
1783 			else
1784 			{
1785 				if (sepac == static_cast<int>(separations.count() - 1))
1786 				{
1787 					aa++;
1788 					sepac = 0;
1789 				}
1790 				else
1791 					sepac++;
1792 			}
1793 		}
1794 		else
1795 			aa++;
1796 	}
1797 	PS_close();
1798 	if (progressDialog)
1799 		progressDialog->close();
1800 	if (errorOccured)
1801 		return 1;
1802 	if (abortExport)
1803 		return 2; //CB Lets leave 1 for general error condition
1804 	return 0;
1805 }
1806 
ProcessItem(ScPage * page,PageItem * item,uint PNr,bool master,bool embedded,bool useTemplate)1807 bool PSLib::ProcessItem(ScPage* page, PageItem* item, uint PNr, bool master, bool embedded, bool useTemplate)
1808 {
1809 	double h, s, v, k;
1810 	QVector<double> dum;
1811 
1812 	if (!item->printEnabled())
1813 		return true;
1814 
1815 	fillRule = true;
1816 	PS_save();
1817 	if (item->doOverprint)
1818 	{
1819 		PutStream("true setoverprint\n");
1820 		PutStream("true setoverprintmode\n");
1821 	}
1822 	if (item->fillColor() != CommonStrings::None)
1823 	{
1824 		SetColor(item->fillColor(), item->fillShade(), &h, &s, &v, &k);
1825 		PS_setcmykcolor_fill(h, s, v, k);
1826 	}
1827 	if (item->lineColor() != CommonStrings::None)
1828 	{
1829 		SetColor(item->lineColor(), item->lineShade(), &h, &s, &v, &k);
1830 		PS_setcmykcolor_stroke(h, s, v, k);
1831 	}
1832 	PS_setlinewidth(item->lineWidth());
1833 	PS_setcapjoin(item->PLineEnd, item->PLineJoin);
1834 	PS_setdash(item->PLineArt, item->DashOffset, item->DashValues);
1835 	if (!embedded)
1836 	{
1837 		PS_translate(item->xPos() - page->xOffset(), page->height() - (item->yPos() - page->yOffset()));
1838 	}
1839 	if (item->rotation() != 0)
1840 		PS_rotate(-item->rotation());
1841 	switch (item->itemType())
1842 	{
1843 	case PageItem::ImageFrame:
1844 	case PageItem::LatexFrame:
1845 		if (master)
1846 			break;
1847 		if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
1848 		{
1849 			SetClipPath(item->PoLine);
1850 			PS_closepath();
1851 			if (item->GrType == Gradient_Hatch)
1852 				PS_HatchFill(item);
1853 			else if ((item->GrType != 0) && (!master))
1854 				HandleGradientFillStroke(item, false);
1855 			else
1856 				putColor(item->fillColor(), item->fillShade(), true);
1857 			PS_newpath();
1858 		}
1859 		PS_save();
1860 		SetPathAndClip(item->PoLine, true);
1861 		if (item->imageFlippedH())
1862 		{
1863 			PS_translate(item->width(), 0);
1864 			PS_scale(-1, 1);
1865 		}
1866 		if (item->imageFlippedV())
1867 		{
1868 			PS_translate(0, -item->height());
1869 			PS_scale(1, -1);
1870 		}
1871 		if (!item->imageClip.empty())
1872 			SetPathAndClip(item->imageClip, true);
1873 		if ((item->imageIsAvailable) && (!item->Pfile.isEmpty()))
1874 		{
1875 			bool imageOk = false;
1876 			PS_translate(0, -item->BBoxH * item->imageYScale());
1877 			if ((m_optimization == OptimizeSize) && (((!page->pageNameEmpty()) && !Options.outputSeparations && Options.useColor) || useTemplate))
1878 				imageOk = PS_image(item, item->imageXOffset(), -item->imageYOffset(), item->Pfile, item->imageXScale(), item->imageYScale(), item->ImageProfile, item->UseEmbedded, item->itemName());
1879 			else
1880 				imageOk = PS_image(item, item->imageXOffset(), -item->imageYOffset(), item->Pfile, item->imageXScale(), item->imageYScale(), item->ImageProfile, item->UseEmbedded);
1881 			if (!imageOk) return false;
1882 		}
1883 		PS_restore();
1884 		if (((item->lineColor() != CommonStrings::None) || (!item->NamedLStyle.isEmpty()) || (!item->strokePattern().isEmpty()) || (item->GrTypeStroke > 0)))
1885 		{
1886 			if (item->NamedLStyle.isEmpty()) // && (item->lineWidth() != 0.0))
1887 			{
1888 				ScPattern* strokePattern = m_Doc->checkedPattern(item->strokePattern());
1889 				if ((strokePattern) && (item->patternStrokePath))
1890 				{
1891 					QPainterPath path = item->PoLine.toQPainterPath(false);
1892 					HandleBrushPattern(item, path, page, PNr, master);
1893 				}
1894 				else
1895 				{
1896 					PS_setlinewidth(item->lineWidth());
1897 					PS_setcapjoin(item->PLineEnd, item->PLineJoin);
1898 					PS_setdash(item->PLineArt, item->DashOffset, item->DashValues);
1899 					SetClipPath(item->PoLine);
1900 					PS_closepath();
1901 					if (strokePattern)
1902 						HandleStrokePattern(item);
1903 					else if (item->GrTypeStroke > 0)
1904 						HandleGradientFillStroke(item);
1905 					else if (item->lineColor() != CommonStrings::None)
1906 					{
1907 						SetColor(item->lineColor(), item->lineShade(), &h, &s, &v, &k);
1908 						PS_setcmykcolor_stroke(h, s, v, k);
1909 						putColor(item->lineColor(), item->lineShade(), false);
1910 					}
1911 				}
1912 			}
1913 			else
1914 			{
1915 				multiLine ml = m_Doc->docLineStyles[item->NamedLStyle];
1916 				for (int it = ml.size() - 1; it > -1; it--)
1917 				{
1918 					if (ml[it].Color != CommonStrings::None) // && (ml[it].Width != 0))
1919 					{
1920 						SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
1921 						PS_setcmykcolor_stroke(h, s, v, k);
1922 						PS_setlinewidth(ml[it].Width);
1923 						PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
1924 						PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
1925 						SetClipPath(item->PoLine);
1926 						PS_closepath();
1927 						putColor(ml[it].Color, ml[it].Shade, false);
1928 					}
1929 				}
1930 			}
1931 		}
1932 		break;
1933 	case PageItem::TextFrame:
1934 		if (master)
1935 			break;
1936 		if ((item->isBookmark || item->isAnnotation()) && (!Options.includePDFMarks))
1937 			break;
1938 		if (item->isBookmark)
1939 		{
1940 			QString bm = "";
1941 			QString cc;
1942 			for (int d = 0; d < item->itemText.length(); ++d)
1943 			{
1944 				if ((item->itemText.text(d) == QChar(13)) || (item->itemText.text(d) == QChar(10)) || (item->itemText.text(d) == QChar(28)))
1945 					break;
1946 				bm += "\\" + cc.setNum(qMax(item->itemText.text(d).unicode(), (ushort) 32), 8);
1947 			}
1948 			PDF_Bookmark(bm, page->pageNr()+1);
1949 		}
1950 		if (item->isAnnotation())
1951 		{
1952 			if ((item->annotation().Type() == 0) || (item->annotation().Type() == 1) || (item->annotation().Type() == Annotation::Text) || (item->annotation().Type() == Annotation::Link))
1953 			{
1954 				QString bm = "";
1955 				QString cc;
1956 				for (int d = 0; d < item->itemText.length(); ++d)
1957 				{
1958 					bm += "\\" + cc.setNum(qMax(item->itemText.text(d).unicode(), (ushort) 32), 8);
1959 				}
1960 				PDF_Annotation(item, bm, 0, 0, item->width(), -item->height());
1961 			}
1962 			break;
1963 		}
1964 		if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
1965 		{
1966 			SetClipPath(item->PoLine);
1967 			PS_closepath();
1968 			if (item->GrType == Gradient_Hatch)
1969 				PS_HatchFill(item);
1970 			else if ((item->GrType != 0) && (!master))
1971 				HandleGradientFillStroke(item, false);
1972 			else
1973 				putColor(item->fillColor(), item->fillShade(), true);
1974 		}
1975 		if (item->imageFlippedH())
1976 		{
1977 			PS_translate(item->width(), 0);
1978 			PS_scale(-1, 1);
1979 		}
1980 		if (item->imageFlippedV())
1981 		{
1982 			PS_translate(0, -item->height());
1983 			PS_scale(1, -1);
1984 		}
1985 		if (item->itemText.length() != 0)
1986 			setTextSt(item, PNr - 1, page, master);
1987 		if (((item->lineColor() != CommonStrings::None) || (!item->NamedLStyle.isEmpty()) || (!item->strokePattern().isEmpty()) || (item->GrTypeStroke > 0)))
1988 		{
1989 			PS_setlinewidth(item->lineWidth());
1990 			PS_setcapjoin(item->PLineEnd, item->PLineJoin);
1991 			PS_setdash(item->PLineArt, item->DashOffset, item->DashValues);
1992 			if (item->NamedLStyle.isEmpty()) // && (item->lineWidth() != 0.0))
1993 			{
1994 				ScPattern* strokePattern = m_Doc->checkedPattern(item->strokePattern());
1995 				if ((strokePattern) && (item->patternStrokePath))
1996 				{
1997 					QPainterPath path = item->PoLine.toQPainterPath(false);
1998 					HandleBrushPattern(item, path, page, PNr, master);
1999 				}
2000 				else
2001 				{
2002 					SetClipPath(item->PoLine);
2003 					PS_closepath();
2004 					if (strokePattern)
2005 						HandleStrokePattern(item);
2006 					else if (item->GrTypeStroke > 0)
2007 						HandleGradientFillStroke(item);
2008 					else if (item->lineColor() != CommonStrings::None)
2009 					{
2010 						SetColor(item->lineColor(), item->lineShade(), &h, &s, &v, &k);
2011 						PS_setcmykcolor_stroke(h, s, v, k);
2012 						putColor(item->lineColor(), item->lineShade(), false);
2013 					}
2014 				}
2015 			}
2016 			else
2017 			{
2018 				multiLine ml = m_Doc->docLineStyles[item->NamedLStyle];
2019 				for (int it = ml.size() - 1; it > -1; it--)
2020 				{
2021 					if (ml[it].Color != CommonStrings::None) //&& (ml[it].Width != 0))
2022 					{
2023 						SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
2024 						PS_setcmykcolor_stroke(h, s, v, k);
2025 						PS_setlinewidth(ml[it].Width);
2026 						PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
2027 						PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
2028 						SetClipPath(item->PoLine);
2029 						PS_closepath();
2030 						putColor(ml[it].Color, ml[it].Shade, false);
2031 					}
2032 				}
2033 			}
2034 		}
2035 		break;
2036 	case PageItem::Line:
2037 		if (item->NamedLStyle.isEmpty()) // && (item->lineWidth() != 0.0))
2038 		{
2039 			ScPattern* strokePattern = m_Doc->checkedPattern(item->strokePattern());
2040 			if (strokePattern)
2041 			{
2042 				if (item->patternStrokePath)
2043 				{
2044 					QPainterPath guidePath;
2045 					guidePath.moveTo(0, 0);
2046 					guidePath.lineTo(item->width(), 0);
2047 					HandleBrushPattern(item, guidePath, page, PNr, master);
2048 				}
2049 				else
2050 				{
2051 					PS_moveto(0, 0);
2052 					PS_lineto(item->width(), 0);
2053 					HandleStrokePattern(item);
2054 				}
2055 			}
2056 			else if (item->GrTypeStroke > 0)
2057 			{
2058 				PS_moveto(0, 0);
2059 				PS_lineto(item->width(), 0);
2060 				HandleGradientFillStroke(item);
2061 			}
2062 			else if (item->lineColor() != CommonStrings::None)
2063 			{
2064 				PS_moveto(0, 0);
2065 				PS_lineto(item->width(), 0);
2066 				putColor(item->lineColor(), item->lineShade(), false);
2067 			}
2068 		}
2069 		else
2070 		{
2071 			multiLine ml = m_Doc->docLineStyles[item->NamedLStyle];
2072 			for (int it = ml.size() - 1; it > -1; it--)
2073 			{
2074 				if (ml[it].Color != CommonStrings::None) //&& (ml[it].Width != 0))
2075 				{
2076 					SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
2077 					PS_setcmykcolor_stroke(h, s, v, k);
2078 					PS_setlinewidth(ml[it].Width);
2079 					PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
2080 					PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
2081 					PS_moveto(0, 0);
2082 					PS_lineto(item->width(), 0);
2083 					putColor(ml[it].Color, ml[it].Shade, false);
2084 				}
2085 			}
2086 		}
2087 		if (item->startArrowIndex() != 0)
2088 		{
2089 			QTransform arrowTrans;
2090 			arrowTrans.scale(-1,1);
2091 			arrowTrans.scale(item->startArrowScale() / 100.0, item->startArrowScale() / 100.0);
2092 			drawArrow(item, arrowTrans, item->startArrowIndex());
2093 		}
2094 		if (item->endArrowIndex() != 0)
2095 		{
2096 			QTransform arrowTrans;
2097 			arrowTrans.translate(item->width(), 0);
2098 			arrowTrans.scale(item->endArrowScale() / 100.0, item->endArrowScale() / 100.0);
2099 			drawArrow(item, arrowTrans, item->endArrowIndex());
2100 		}
2101 		break;
2102 	/* OBSOLETE CR 2005-02-06
2103 	case 1:
2104 	case 3:
2105 	*/
2106 	case PageItem::ItemType1:
2107 	case PageItem::ItemType3:
2108 	case PageItem::Polygon:
2109 	case PageItem::RegularPolygon:
2110 	case PageItem::Arc:
2111 		if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
2112 		{
2113 			SetClipPath(item->PoLine);
2114 			PS_closepath();
2115 			fillRule = item->fillRule;
2116 			if (item->GrType == Gradient_Hatch)
2117 				PS_HatchFill(item);
2118 			else if (item->GrType != 0)
2119 				HandleGradientFillStroke(item, false);
2120 			else
2121 				putColor(item->fillColor(), item->fillShade(), true);
2122 		}
2123 		if ((item->lineColor() != CommonStrings::None) || (!item->NamedLStyle.isEmpty()) || (!item->strokePattern().isEmpty()) || (item->GrTypeStroke > 0))
2124 		{
2125 			if (item->NamedLStyle.isEmpty()) //&& (item->lineWidth() != 0.0))
2126 			{
2127 				ScPattern* strokePattern = m_Doc->checkedPattern(item->strokePattern());
2128 				if (strokePattern && (item->patternStrokePath))
2129 				{
2130 					QPainterPath path = item->PoLine.toQPainterPath(false);
2131 					HandleBrushPattern(item, path, page, PNr, master);
2132 				}
2133 				else
2134 				{
2135 					SetClipPath(item->PoLine);
2136 					PS_closepath();
2137 					if (strokePattern)
2138 						HandleStrokePattern(item);
2139 					else if (item->GrTypeStroke > 0)
2140 						HandleGradientFillStroke(item);
2141 					else if (item->lineColor() != CommonStrings::None)
2142 						putColor(item->lineColor(), item->lineShade(), false);
2143 				}
2144 			}
2145 			else
2146 			{
2147 				multiLine ml = m_Doc->docLineStyles[item->NamedLStyle];
2148 				for (int it = ml.size() - 1; it > -1; it--)
2149 				{
2150 					if (ml[it].Color != CommonStrings::None) //&& (ml[it].Width != 0))
2151 					{
2152 						SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
2153 						PS_setcmykcolor_stroke(h, s, v, k);
2154 						PS_setlinewidth(ml[it].Width);
2155 						PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
2156 						PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
2157 						SetClipPath(item->PoLine);
2158 						PS_closepath();
2159 						putColor(ml[it].Color, ml[it].Shade, false);
2160 					}
2161 				}
2162 			}
2163 		}
2164 		break;
2165 	case PageItem::PolyLine:
2166 	case PageItem::Spiral:
2167 		if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
2168 		{
2169 			SetClipPath(item->PoLine);
2170 			PS_closepath();
2171 			fillRule = item->fillRule;
2172 			if (item->GrType == Gradient_Hatch)
2173 				PS_HatchFill(item);
2174 			else if (item->GrType != 0)
2175 				HandleGradientFillStroke(item, false);
2176 			else
2177 				putColor(item->fillColor(), item->fillShade(), true);
2178 			PS_newpath();
2179 		}
2180 		if ((item->lineColor() != CommonStrings::None) || (!item->NamedLStyle.isEmpty()) || (!item->strokePattern().isEmpty()) || (item->GrTypeStroke > 0))
2181 		{
2182 			if (item->NamedLStyle.isEmpty()) //&& (item->lineWidth() != 0.0))
2183 			{
2184 				ScPattern* strokePattern = m_Doc->checkedPattern(item->strokePattern());
2185 				if (strokePattern && (item->patternStrokePath))
2186 				{
2187 					QPainterPath path = item->PoLine.toQPainterPath(false);
2188 					HandleBrushPattern(item, path, page, PNr, master);
2189 				}
2190 				else
2191 				{
2192 					SetClipPath(item->PoLine, false);
2193 					if (strokePattern)
2194 						HandleStrokePattern(item);
2195 					else if (item->GrTypeStroke > 0)
2196 						HandleGradientFillStroke(item);
2197 					else if (item->lineColor() != CommonStrings::None)
2198 						putColor(item->lineColor(), item->lineShade(), false);
2199 				}
2200 			}
2201 			else
2202 			{
2203 				multiLine ml = m_Doc->docLineStyles[item->NamedLStyle];
2204 				for (int it = ml.size() - 1; it > -1; it--)
2205 				{
2206 					if (ml[it].Color != CommonStrings::None) //&& (ml[it].Width != 0))
2207 					{
2208 						SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
2209 						PS_setcmykcolor_stroke(h, s, v, k);
2210 						PS_setlinewidth(ml[it].Width);
2211 						PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
2212 						PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
2213 						SetClipPath(item->PoLine, false);
2214 						putColor(ml[it].Color, ml[it].Shade, false);
2215 					}
2216 				}
2217 			}
2218 		}
2219 		if (item->startArrowIndex() != 0)
2220 		{
2221 			FPoint Start = item->PoLine.point(0);
2222 			for (int xx = 1; xx < item->PoLine.size(); xx += 2)
2223 			{
2224 				FPoint Vector = item->PoLine.point(xx);
2225 				if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
2226 				{
2227 					double r = atan2(Start.y() - Vector.y(), Start.x() - Vector.x()) * (180.0 / M_PI);
2228 					QTransform arrowTrans;
2229 					arrowTrans.translate(Start.x(), Start.y());
2230 					arrowTrans.rotate(r);
2231 					arrowTrans.scale(item->startArrowScale() / 100.0, item->startArrowScale() / 100.0);
2232 					drawArrow(item, arrowTrans, item->startArrowIndex());
2233 					break;
2234 				}
2235 			}
2236 		}
2237 		if (item->endArrowIndex() != 0)
2238 		{
2239 			FPoint End = item->PoLine.point(item->PoLine.size() - 2);
2240 			for (uint xx = item->PoLine.size() - 1; xx > 0; xx -= 2)
2241 			{
2242 				FPoint Vector = item->PoLine.point(xx);
2243 				if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
2244 				{
2245 					double r = atan2(End.y() - Vector.y(),End.x() - Vector.x())*(180.0/M_PI);
2246 					QTransform arrowTrans;
2247 					arrowTrans.translate(End.x(), End.y());
2248 					arrowTrans.rotate(r);
2249 					arrowTrans.scale(item->endArrowScale() / 100.0, item->endArrowScale() / 100.0);
2250 					drawArrow(item, arrowTrans, item->endArrowIndex());
2251 					break;
2252 				}
2253 			}
2254 		}
2255 		break;
2256 	case PageItem::PathText:
2257 		if (master)
2258 			break;
2259 		if (item->PoShow)
2260 		{
2261 			if (item->PoLine.size() > 3)
2262 			{
2263 				PS_save();
2264 				if (item->NamedLStyle.isEmpty()) //&& (item->lineWidth() != 0.0))
2265 				{
2266 					ScPattern* strokePattern = m_Doc->checkedPattern(item->strokePattern());
2267 					if (strokePattern && (item->patternStrokePath))
2268 					{
2269 						QPainterPath path = item->PoLine.toQPainterPath(false);
2270 						HandleBrushPattern(item, path, page, PNr, master);
2271 					}
2272 					else
2273 					{
2274 						SetClipPath(item->PoLine, false);
2275 						if (strokePattern)
2276 							HandleStrokePattern(item);
2277 						else if (item->GrTypeStroke > 0)
2278 							HandleGradientFillStroke(item);
2279 						else if (item->lineColor() != CommonStrings::None)
2280 							putColor(item->lineColor(), item->lineShade(), false);
2281 					}
2282 				}
2283 				else
2284 				{
2285 					multiLine ml = m_Doc->docLineStyles[item->NamedLStyle];
2286 					for (int it = ml.size() - 1; it > -1; it--)
2287 					{
2288 						if (ml[it].Color != CommonStrings::None) //&& (ml[it].Width != 0))
2289 						{
2290 							SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
2291 							PS_setcmykcolor_stroke(h, s, v, k);
2292 							PS_setlinewidth(ml[it].Width);
2293 							PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
2294 							PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
2295 							SetClipPath(item->PoLine, false);
2296 							putColor(ml[it].Color, ml[it].Shade, false);
2297 						}
2298 					}
2299 				}
2300 				PS_restore();
2301 			}
2302 		}
2303 		if (item->itemText.length() != 0)
2304 			setTextSt(item, PNr-1, page, master);
2305 		break;
2306 	case PageItem::Symbol:
2307 		if (m_Doc->docPatterns.contains(item->pattern()))
2308 		{
2309 			ScPattern pat = m_Doc->docPatterns[item->pattern()];
2310 			PS_save();
2311 			SetPathAndClip(item->PoLine, item->fillRule);
2312 			if (item->imageFlippedH())
2313 			{
2314 				PS_translate(item->width(), 0);
2315 				PS_scale(-1, 1);
2316 			}
2317 			if (item->imageFlippedV())
2318 			{
2319 				PS_translate(0, -item->height());
2320 				PS_scale(1, -1);
2321 			}
2322 			PS_scale(item->width() / pat.width, item->height() / pat.height);
2323 			PS_translate(0, -item->height());
2324 //			PS_translate(pat.items.at(0)->gXpos, -pat.items.at(0)->gYpos);
2325 			for (int em = 0; em < pat.items.count(); ++em)
2326 			{
2327 				PageItem* embed = pat.items.at(em);
2328 				PS_save();
2329 				PS_translate(embed->gXpos, item->height() - embed->gYpos);
2330 				ProcessItem(page, embed, PNr, master, true, useTemplate);
2331 				PS_restore();
2332 			}
2333 			PS_restore();
2334 		}
2335 		break;
2336 	case PageItem::Group:
2337 		if (master)
2338 			break;
2339 		PS_save();
2340 		if (item->groupClipping())
2341 			SetPathAndClip(item->PoLine, item->fillRule);
2342 		if (item->imageFlippedH())
2343 		{
2344 			PS_translate(item->width(), 0);
2345 			PS_scale(-1, 1);
2346 		}
2347 		if (item->imageFlippedV())
2348 		{
2349 			PS_translate(0, -item->height());
2350 			PS_scale(1, -1);
2351 		}
2352 		PS_scale(item->width() / item->groupWidth, item->height() / item->groupHeight);
2353 		PS_translate(0, -item->height());
2354 		for (int em = 0; em < item->groupItemList.count(); ++em)
2355 		{
2356 			PageItem* embed = item->groupItemList.at(em);
2357 			PS_save();
2358 			PS_translate(embed->gXpos, item->height() - embed->gYpos);
2359 			ProcessItem(page, embed, PNr, master, true, useTemplate);
2360 			PS_restore();
2361 		}
2362 		PS_restore();
2363 		break;
2364 	case PageItem::Table:
2365 		if (master)
2366 			break;
2367 		PS_save();
2368 		PS_translate(item->asTable()->gridOffset().x(), -item->asTable()->gridOffset().y());
2369 		// Paint table fill.
2370 		if (item->asTable()->fillColor() != CommonStrings::None)
2371 		{
2372 			int lastCol = item->asTable()->columns() - 1;
2373 			int lastRow = item->asTable()->rows() - 1;
2374 			double x = item->asTable()->columnPosition(0);
2375 			double y = item->asTable()->rowPosition(0);
2376 			double width = item->asTable()->columnPosition(lastCol) + item->asTable()->columnWidth(lastCol) - x;
2377 			double height = item->asTable()->rowPosition(lastRow) + item->asTable()->rowHeight(lastRow) - y;
2378 			putColorNoDraw(item->asTable()->fillColor(), item->asTable()->fillShade());
2379 			PutStream("0 0 " + ToStr(width) + " " + ToStr(-height) + " rectfill\n");
2380 		}
2381 		// Pass 1: Paint cell fills.
2382 		for (int row = 0; row < item->asTable()->rows(); ++row)
2383 		{
2384 			int colSpan = 0;
2385 			for (int col = 0; col < item->asTable()->columns(); col += colSpan)
2386 			{
2387 				TableCell cell = item->asTable()->cellAt(row, col);
2388 				if (row == cell.row())
2389 				{
2390 					QString colorName = cell.fillColor();
2391 					if (colorName != CommonStrings::None)
2392 					{
2393 						PS_save();
2394 						putColorNoDraw(colorName, cell.fillShade());
2395 						int row = cell.row();
2396 						int col = cell.column();
2397 						int lastRow = row + cell.rowSpan() - 1;
2398 						int lastCol = col + cell.columnSpan() - 1;
2399 						double x = item->asTable()->columnPosition(col);
2400 						double y = item->asTable()->rowPosition(row);
2401 						double width = item->asTable()->columnPosition(lastCol) + item->asTable()->columnWidth(lastCol) - x;
2402 						double height = item->asTable()->rowPosition(lastRow) + item->asTable()->rowHeight(lastRow) - y;
2403 						PutStream(ToStr(x) + " " + ToStr(-y) + " " + ToStr(width) + " " + ToStr(-height) + " rectfill\n");
2404 						PS_restore();
2405 					}
2406 				}
2407 				colSpan = cell.columnSpan();
2408 			}
2409 		}
2410 		// Pass 2: Paint vertical borders.
2411 		for (int row = 0; row < item->asTable()->rows(); ++row)
2412 		{
2413 			int colSpan = 0;
2414 			for (int col = 0; col < item->asTable()->columns(); col += colSpan)
2415 			{
2416 				TableCell cell = item->asTable()->cellAt(row, col);
2417 				if (row == cell.row())
2418 				{
2419 					const int lastRow = cell.row() + cell.rowSpan() - 1;
2420 					const int lastCol = cell.column() + cell.columnSpan() - 1;
2421 					const double borderX = item->asTable()->columnPosition(lastCol) + item->asTable()->columnWidth(lastCol);
2422 					QPointF start(borderX, 0.0);
2423 					QPointF end(borderX, 0.0);
2424 					QPointF startOffsetFactors, endOffsetFactors;
2425 					int startRow, endRow;
2426 					for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
2427 					{
2428 						TableCell rightCell = item->asTable()->cellAt(row, lastCol + 1);
2429 						startRow = qMax(cell.row(), rightCell.row());
2430 						endRow = qMin(lastRow, rightCell.isValid() ? rightCell.row() + rightCell.rowSpan() - 1 : lastRow);
2431 						TableCell topLeftCell = item->asTable()->cellAt(startRow - 1, lastCol);
2432 						TableCell topRightCell = item->asTable()->cellAt(startRow - 1, lastCol + 1);
2433 						TableCell bottomRightCell = item->asTable()->cellAt(endRow + 1, lastCol + 1);
2434 						TableCell bottomLeftCell = item->asTable()->cellAt(endRow + 1, lastCol);
2435 						TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
2436 						resolveBordersVertical(topLeftCell, topRightCell, cell, rightCell, bottomLeftCell, bottomRightCell,
2437 							&topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, item->asTable());
2438 						if (border.isNull())
2439 							continue; // Quit early if the border to paint is null.
2440 						start.setY(item->asTable()->rowPosition(startRow));
2441 						end.setY((item->asTable()->rowPosition(endRow) + item->asTable()->rowHeight(endRow)));
2442 						joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
2443 						paintBorder(border, start, end, startOffsetFactors, endOffsetFactors);
2444 					}
2445 					if (col == 0)
2446 					{
2447 						const int lastRow = cell.row() + cell.rowSpan() - 1;
2448 						const int firstCol = cell.column();
2449 						const double borderX = item->asTable()->columnPosition(firstCol);
2450 						QPointF start(borderX, 0.0);
2451 						QPointF end(borderX, 0.0);
2452 						QPointF startOffsetFactors, endOffsetFactors;
2453 						int startRow, endRow;
2454 						for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
2455 						{
2456 							TableCell leftCell = item->asTable()->cellAt(row, firstCol - 1);
2457 							startRow = qMax(cell.row(), leftCell.row());
2458 							endRow = qMin(lastRow, leftCell.isValid() ? leftCell.row() + leftCell.rowSpan() - 1 : lastRow);
2459 							TableCell topLeftCell = item->asTable()->cellAt(startRow - 1, firstCol - 1);
2460 							TableCell topRightCell = item->asTable()->cellAt(startRow - 1, firstCol);
2461 							TableCell bottomRightCell = item->asTable()->cellAt(lastRow + 1, firstCol);
2462 							TableCell bottomLeftCell = item->asTable()->cellAt(lastRow + 1, firstCol - 1);
2463 							TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
2464 							resolveBordersVertical(topLeftCell, topRightCell, leftCell, cell, bottomLeftCell, bottomRightCell,
2465 								&topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, item->asTable());
2466 							if (border.isNull())
2467 								continue; // Quit early if the border to paint is null.
2468 							start.setY(item->asTable()->rowPosition(startRow));
2469 							end.setY((item->asTable()->rowPosition(endRow) + item->asTable()->rowHeight(endRow)));
2470 							joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
2471 							paintBorder(border, start, end, startOffsetFactors, endOffsetFactors);
2472 						}
2473 					}
2474 				}
2475 				colSpan = cell.columnSpan();
2476 			}
2477 		}
2478 		// Pass 3: Paint horizontal borders.
2479 		for (int row = 0; row < item->asTable()->rows(); ++row)
2480 		{
2481 			int colSpan = 0;
2482 			for (int col = 0; col < item->asTable()->columns(); col += colSpan)
2483 			{
2484 				TableCell cell = item->asTable()->cellAt(row, col);
2485 				if (row == cell.row())
2486 				{
2487 					const int lastRow = cell.row() + cell.rowSpan() - 1;
2488 					const int lastCol = cell.column() + cell.columnSpan() - 1;
2489 					const double borderY = (item->asTable()->rowPosition(lastRow) + item->asTable()->rowHeight(lastRow));
2490 					QPointF start(0.0, borderY);
2491 					QPointF end(0.0, borderY);
2492 					QPointF startOffsetFactors, endOffsetFactors;
2493 					int startCol, endCol;
2494 					for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
2495 					{
2496 						TableCell bottomCell = item->asTable()->cellAt(lastRow + 1, col);
2497 						startCol = qMax(cell.column(), bottomCell.column());
2498 						endCol = qMin(lastCol, bottomCell.isValid() ? bottomCell.column() + bottomCell.columnSpan() - 1 : lastCol);
2499 						TableCell topLeftCell = item->asTable()->cellAt(lastRow, startCol - 1);
2500 						TableCell topRightCell = item->asTable()->cellAt(lastRow, endCol + 1);
2501 						TableCell bottomRightCell = item->asTable()->cellAt(lastRow + 1, endCol + 1);
2502 						TableCell bottomLeftCell = item->asTable()->cellAt(lastRow + 1, startCol - 1);
2503 						TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
2504 						resolveBordersHorizontal(topLeftCell, cell, topRightCell, bottomLeftCell, bottomCell,
2505 											bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, item->asTable());
2506 						if (border.isNull())
2507 							continue; // Quit early if the border is null.
2508 						start.setX(item->asTable()->columnPosition(startCol));
2509 						end.setX(item->asTable()->columnPosition(endCol) + item->asTable()->columnWidth(endCol));
2510 						joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
2511 						paintBorder(border, start, end, startOffsetFactors, endOffsetFactors);
2512 					}
2513 					if (row == 0)
2514 					{
2515 						const int firstRow = cell.row();
2516 						const int lastCol = cell.column() + cell.columnSpan() - 1;
2517 						const double borderY = item->asTable()->rowPosition(firstRow);
2518 						QPointF start(0.0, borderY);
2519 						QPointF end(0.0, borderY);
2520 						QPointF startOffsetFactors, endOffsetFactors;
2521 						int startCol, endCol;
2522 						for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
2523 						{
2524 							TableCell topCell = item->asTable()->cellAt(firstRow - 1, col);
2525 							startCol = qMax(cell.column(), topCell.column());
2526 							endCol = qMin(lastCol, topCell.isValid() ? topCell.column() + topCell.columnSpan() - 1 : lastCol);
2527 							TableCell topLeftCell = item->asTable()->cellAt(firstRow - 1, startCol - 1);
2528 							TableCell topRightCell = item->asTable()->cellAt(firstRow - 1, endCol + 1);
2529 							TableCell bottomRightCell = item->asTable()->cellAt(firstRow, endCol + 1);
2530 							TableCell bottomLeftCell = item->asTable()->cellAt(firstRow, startCol - 1);
2531 							TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
2532 							resolveBordersHorizontal(topLeftCell, topCell, topRightCell, bottomLeftCell, cell,
2533 														bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, item->asTable());
2534 							if (border.isNull())
2535 								continue; // Quit early if the border is null.
2536 							start.setX(item->asTable()->columnPosition(startCol));
2537 							end.setX(item->asTable()->columnPosition(endCol) + item->asTable()->columnWidth(endCol));
2538 							joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
2539 							paintBorder(border, start, end, startOffsetFactors, endOffsetFactors);
2540 						}
2541 					}
2542 				}
2543 				colSpan = cell.columnSpan();
2544 			}
2545 		}
2546 		// Pass 4: Paint cell content.
2547 		for (int row = 0; row < item->asTable()->rows(); ++row)
2548 		{
2549 			for (int col = 0; col < item->asTable()->columns(); col ++)
2550 			{
2551 				TableCell cell = item->asTable()->cellAt(row, col);
2552 				if (cell.row() == row && cell.column() == col)
2553 				{
2554 					PageItem* textFrame = cell.textFrame();
2555 					PS_save();
2556 					PS_translate(cell.contentRect().x(), -cell.contentRect().y());
2557 					ProcessItem(page, textFrame, PNr, master, true);
2558 					PS_restore();
2559 				}
2560 			}
2561 		}
2562 		PS_restore();
2563 		break;
2564 	default:
2565 		break;
2566 	}
2567 	PS_restore();
2568 
2569 	return true;
2570 }
2571 
2572 
paintBorder(const TableBorder & border,const QPointF & start,const QPointF & end,const QPointF & startOffsetFactors,const QPointF & endOffsetFactors)2573 void PSLib::paintBorder(const TableBorder& border, const QPointF& start, const QPointF& end, const QPointF& startOffsetFactors, const QPointF& endOffsetFactors)
2574 {
2575 	PS_save();
2576 	QPointF lineStart, lineEnd;
2577 	QVector<double> DashValues;
2578 	for (const TableBorderLine& line : border.borderLines())
2579 	{
2580 		if (line.color() == CommonStrings::None)
2581 			continue;
2582 		lineStart.setX(start.x() + line.width() * startOffsetFactors.x());
2583 		lineStart.setY(start.y() + line.width() * startOffsetFactors.y());
2584 		lineEnd.setX(end.x() + line.width() * endOffsetFactors.x());
2585 		lineEnd.setY(end.y() + line.width() * endOffsetFactors.y());
2586 		PS_moveto(lineStart.x(), -lineStart.y());
2587 		PS_lineto(lineEnd.x(), -lineEnd.y());
2588 		PS_setlinewidth(line.width());
2589 		getDashArray(line.style(), qMax(line.width(), 1.0), DashValues);
2590 		PS_setdash(line.style(), 0, DashValues);
2591 		double h, s, v, k;
2592 		SetColor(line.color(), line.shade(), &h, &s, &v, &k);
2593 		PS_setcmykcolor_stroke(h, s, v, k);
2594 		PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
2595 		putColor(line.color(), line.shade(), false);
2596 	}
2597 	PS_restore();
2598 }
2599 
ProcessPage(ScPage * page,uint PNr)2600 void PSLib::ProcessPage(ScPage* page, uint PNr)
2601 {
2602 	PageItem *item;
2603 	QList<PageItem*> pageItems = (page->pageNameEmpty()) ? m_Doc->DocItems : m_Doc->MasterItems;
2604 
2605 	ScLayer ll;
2606 	ll.isPrintable = false;
2607 	ll.ID = 0;
2608 
2609 	for (int layerLevel = 0; layerLevel < m_Doc->Layers.count(); ++layerLevel)
2610 	{
2611 		m_Doc->Layers.levelToLayer(ll, layerLevel);
2612 		if (!ll.isPrintable)
2613 			continue;
2614 		for (int i = 0; i < pageItems.count() && !abortExport; ++i)
2615 		{
2616 			item = pageItems.at(i);
2617 			if (progressDialog)
2618 				ScQApp->processEvents();
2619 			if (item->m_layerID != ll.ID)
2620 				continue;
2621 			if ((!page->pageNameEmpty()) && (item->isTextContainer()))
2622 				continue;
2623 			if ((!page->pageNameEmpty()) && (item->isImageFrame()) && ((Options.outputSeparations) || (!Options.useColor)))
2624 				continue;
2625 			//if ((!Art) && (view->SelItem.count() != 0) && (!item->Select))
2626 			if ((m_outputFormat == OutputEPS) && (!item->isSelected()) && (m_Doc->m_Selection->count() != 0))
2627 				continue;
2628 			double bLeft, bRight, bBottom, bTop;
2629 			GetBleeds(page, bLeft, bRight, bBottom, bTop);
2630 			double x1 = page->xOffset() - bLeft;
2631 			double y1 = page->yOffset() - bTop;
2632 			double w1 = page->width() + bLeft + bRight;
2633 			double h1 = page->height() + bBottom + bTop;
2634 			double lw = item->visualLineWidth();
2635 			double x2 = item->BoundingX - lw / 2.0;
2636 			double y2 = item->BoundingY - lw / 2.0;
2637 			double w2 = qMax(item->BoundingW + lw, 1.0);
2638 			double h2 = qMax(item->BoundingH + lw, 1.0);
2639 			if (!QRectF(x2, y2, w2, h2).intersects(QRectF(x1, y1, w1, h1)))
2640 				continue;
2641 			if (item->ChangedMasterItem)
2642 				continue;
2643 			if ((!page->pageNameEmpty()) && (item->OwnPage != page->pageNr()) && (item->OwnPage != -1))
2644 				continue;
2645 			ProcessItem(page, item, PNr, false);
2646 		}
2647 	}
2648 }
2649 
ProcessMasterPageLayer(ScPage * page,ScLayer & layer,uint PNr)2650 bool PSLib::ProcessMasterPageLayer(ScPage* page, ScLayer& layer, uint PNr)
2651 {
2652 	bool success = true;
2653 	double h, s, v, k;
2654 	QVector<double> dum;
2655 	ScPage* mPage = m_Doc->MasterPages.at(m_Doc->MasterNames[page->masterPageName()]);
2656 	if (layer.isPrintable)
2657 	{
2658 		for (int am = 0; am < page->FromMaster.count() && !abortExport; ++am)
2659 		{
2660 			PageItem *ite = page->FromMaster.at(am);
2661 			if (progressDialog)
2662 				ScQApp->processEvents();
2663 			if ((ite->m_layerID != layer.ID) || (!ite->printEnabled()))
2664 				continue;
2665 			if (!ite->isTextContainer())
2666 			{
2667 				int mpIndex = m_Doc->MasterNames[page->masterPageName()];
2668 				PS_UseTemplate(QString("mp_obj_%1_%2").arg(mpIndex).arg(qHash(ite)));
2669 			}
2670 			else if (!ite->isTextFrame())
2671 			{
2672 				PS_save();
2673 				// JG : replace what seems mostly duplicate code by corresponding function call (#3936)
2674 				success &= ProcessItem(mPage, ite, PNr, false, false, true);
2675 				PS_restore();
2676 			}
2677 			else // if (ite->isTextFrame())
2678 			{
2679 				PS_save();
2680 				if (ite->doOverprint)
2681 				{
2682 					PutStream("true setoverprint\n");
2683 					PutStream("true setoverprintmode\n");
2684 				}
2685 				if (ite->fillColor() != CommonStrings::None)
2686 				{
2687 					SetColor(ite->fillColor(), ite->fillShade(), &h, &s, &v, &k);
2688 					PS_setcmykcolor_fill(h, s, v, k);
2689 				}
2690 				PS_translate(ite->xPos() - mPage->xOffset(), mPage->height() - (ite->yPos() - mPage->yOffset()));
2691 				if (ite->rotation() != 0)
2692 					PS_rotate(-ite->rotation());
2693 				if ((ite->fillColor() != CommonStrings::None) || (ite->GrType != 0))
2694 				{
2695 					SetClipPath(ite->PoLine);
2696 					PS_closepath();
2697 					if (ite->GrType == Gradient_Hatch)
2698 						PS_HatchFill(ite);
2699 					else if (ite->GrType != 0)
2700 						HandleGradientFillStroke(ite, false);
2701 					else
2702 						putColor(ite->fillColor(), ite->fillShade(), true);
2703 				}
2704 				if (ite->imageFlippedH())
2705 				{
2706 					PS_translate(ite->width(), 0);
2707 					PS_scale(-1, 1);
2708 				}
2709 				if (ite->imageFlippedV())
2710 				{
2711 					PS_translate(0, -ite->height());
2712 					PS_scale(1, -1);
2713 				}
2714 				if (ite->itemText.length() != 0)
2715 					setTextSt(ite, PNr - 1, mPage, true);
2716 				if (((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()) || (!ite->strokePattern().isEmpty()) || (ite->GrTypeStroke > 0)))
2717 				{
2718 					PS_setlinewidth(ite->lineWidth());
2719 					PS_setcapjoin(ite->PLineEnd, ite->PLineJoin);
2720 					PS_setdash(ite->PLineArt, ite->DashOffset, ite->DashValues);
2721 					if (ite->NamedLStyle.isEmpty()) // && (ite->lineWidth() != 0.0))
2722 					{
2723 						ScPattern* strokePattern = m_Doc->checkedPattern(ite->strokePattern());
2724 						if (strokePattern && (ite->patternStrokePath))
2725 						{
2726 							QPainterPath path = ite->PoLine.toQPainterPath(false);
2727 							HandleBrushPattern(ite, path, page, PNr, true);
2728 						}
2729 						else
2730 						{
2731 							SetClipPath(ite->PoLine);
2732 							PS_closepath();
2733 							if (strokePattern)
2734 								HandleStrokePattern(ite);
2735 							else if (ite->GrTypeStroke > 0)
2736 								HandleGradientFillStroke(ite);
2737 							else if (ite->lineColor() != CommonStrings::None)
2738 							{
2739 								SetColor(ite->lineColor(), ite->lineShade(), &h, &s, &v, &k);
2740 								PS_setcmykcolor_stroke(h, s, v, k);
2741 								putColor(ite->lineColor(), ite->lineShade(), false);
2742 							}
2743 						}
2744 					}
2745 					else
2746 					{
2747 						multiLine ml = m_Doc->docLineStyles[ite->NamedLStyle];
2748 						for (int it = ml.size() - 1; it > -1; it--)
2749 						{
2750 							if (ml[it].Color != CommonStrings::None) //&& (ml[it].Width != 0))
2751 							{
2752 								SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
2753 								PS_setcmykcolor_stroke(h, s, v, k);
2754 								PS_setlinewidth(ml[it].Width);
2755 								PS_setcapjoin(static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
2756 								PS_setdash(static_cast<Qt::PenStyle>(ml[it].Dash), 0, dum);
2757 								SetClipPath(ite->PoLine);
2758 								PS_closepath();
2759 								putColor(ml[it].Color, ml[it].Shade, false);
2760 							}
2761 						}
2762 					}
2763 				}
2764 				PS_restore();
2765 			}
2766 			if (!success)
2767 				break;
2768 		}
2769 	}
2770 	return success;
2771 }
2772 
ProcessPageLayer(ScPage * page,ScLayer & layer,uint PNr)2773 bool PSLib::ProcessPageLayer(ScPage* page, ScLayer& layer, uint PNr)
2774 {
2775 	bool success = true;
2776 	if (!layer.isPrintable || abortExport)
2777 		return true;
2778 
2779 	QList<PageItem*> items;
2780 	items = (page->pageNameEmpty()) ? m_Doc->DocItems : m_Doc->MasterItems;
2781 
2782 	for (int i = 0; i < items.count() && !abortExport; ++i)
2783 	{
2784 		PageItem *item = items.at(i);
2785 		if (progressDialog)
2786 			ScQApp->processEvents();
2787 		if (item->m_layerID != layer.ID)
2788 			continue;
2789 		if ((!page->pageNameEmpty()) && (item->isTextContainer()))
2790 			continue;
2791 		if ((!page->pageNameEmpty()) && (item->isImageFrame()) && ((Options.outputSeparations) || (!Options.useColor)))
2792 			continue;
2793 		//if ((!Art) && (view->SelItem.count() != 0) && (!item->Select))
2794 		if ((m_outputFormat == OutputEPS) && (!item->isSelected()) && (m_Doc->m_Selection->count() != 0))
2795 			continue;
2796 		double bLeft, bRight, bBottom, bTop;
2797 		GetBleeds(page, bLeft, bRight, bBottom, bTop);
2798 		double x1 = page->xOffset() - bLeft;
2799 		double y1 = page->yOffset() - bTop;
2800 		double w1 = page->width() + bLeft + bRight;
2801 		double h1 = page->height() + bBottom + bTop;
2802 		double lw = item->visualLineWidth();
2803 		double x2 = item->BoundingX - lw / 2.0;
2804 		double y2 = item->BoundingY - lw / 2.0;
2805 		double w2 = qMax(item->BoundingW + lw, 1.0);
2806 		double h2 = qMax(item->BoundingH + lw, 1.0);
2807 		if (!QRectF(x2, y2, w2, h2).intersects(QRectF(x1, y1, w1, h1)))
2808 			continue;
2809 		if (item->ChangedMasterItem)
2810 			continue;
2811 		if ((!page->pageNameEmpty()) && (item->OwnPage != page->pageNr()) && (item->OwnPage != -1))
2812 			continue;
2813 		success &= ProcessItem(page, item, PNr, false);
2814 		if (!success)
2815 			break;
2816 	}
2817 	return success;
2818 }
2819 
2820 
HandleBrushPattern(PageItem * item,QPainterPath & path,ScPage * page,uint PNr,bool master)2821 void PSLib::HandleBrushPattern(PageItem *item, QPainterPath &path, ScPage* page, uint PNr, bool master)
2822 {
2823 	ScPattern pat = m_Doc->docPatterns[item->strokePattern()];
2824 	double pLen = path.length() - ((pat.width / 2.0) * (item->patternStrokeScaleX / 100.0));
2825 	double adv = pat.width * item->patternStrokeScaleX / 100.0 * item->patternStrokeSpace;
2826 	double xpos = item->patternStrokeOffsetX * item->patternStrokeScaleX / 100.0;
2827 	while (xpos < pLen)
2828 	{
2829 		double currPerc = path.percentAtLength(xpos);
2830 		double currAngle = path.angleAtPercent(currPerc);
2831 		if (currAngle <= 180.0)
2832 			currAngle *= -1.0;
2833 		else
2834 			currAngle = 360.0 - currAngle;
2835 		QPointF currPoint = path.pointAtPercent(currPerc);
2836 		PS_save();
2837 		PS_translate(currPoint.x(), -currPoint.y());
2838 		PS_rotate(-currAngle);
2839 		QTransform trans;
2840 		trans.translate(0.0, -item->patternStrokeOffsetY);
2841 		trans.rotate(-item->patternStrokeRotation);
2842 		trans.shear(item->patternStrokeSkewX, -item->patternStrokeSkewY);
2843 		trans.scale(item->patternStrokeScaleX / 100.0, item->patternStrokeScaleY / 100.0);
2844 		trans.translate(-pat.width / 2.0, -pat.height / 2.0);
2845 		if (item->patternStrokeMirrorX)
2846 		{
2847 			trans.translate(pat.width, 0);
2848 			trans.scale(-1, 1);
2849 		}
2850 		if (item->patternStrokeMirrorY)
2851 		{
2852 			trans.translate(0, pat.height);
2853 			trans.scale(1, -1);
2854 		}
2855 		PutStream( MatrixToStr(trans.m11(), trans.m12(), trans.m21(), trans.m22(), trans.dx(), trans.dy()) + " concat\n");
2856 		for (int em = 0; em < pat.items.count(); ++em)
2857 		{
2858 			PageItem* embedded = pat.items.at(em);
2859 			PS_save();
2860 			PS_translate(embedded->gXpos, embedded->gHeight - embedded->gYpos);
2861 			ProcessItem(page, embedded, PNr, master, true);
2862 			PS_restore();
2863 		}
2864 		xpos += adv;
2865 		PS_restore();
2866 	}
2867 }
2868 
HandleStrokePattern(PageItem * item)2869 void PSLib::HandleStrokePattern(PageItem *item)
2870 {
2871 	ScPattern *pat;
2872 	QTransform patternMatrix;
2873 	double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace;
2874 	pat = &m_Doc->docPatterns[item->strokePattern()];
2875 	uint patHash = qHash(item->strokePattern());
2876 	item->strokePatternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace);
2877 	patternMatrix.translate(-item->lineWidth() / 2.0, item->lineWidth() / 2.0);
2878 	patternMatrix.translate(patternOffsetX, -patternOffsetY);
2879 	patternMatrix.rotate(-patternRotation);
2880 	patternMatrix.shear(patternSkewX, -patternSkewY);
2881 	patternMatrix.scale(pat->scaleX, pat->scaleY);
2882 	patternMatrix.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
2883 	bool mirrorX, mirrorY;
2884 	item->strokePatternFlip(mirrorX, mirrorY);
2885 	if (mirrorX)
2886 		patternMatrix.scale(-1, 1);
2887 	if (mirrorY)
2888 		patternMatrix.scale(1, -1);
2889 	PutStream("Pattern" + QString::number(patHash) + " [" + ToStr(patternMatrix.m11()) + " " + ToStr(patternMatrix.m12()) + " " + ToStr(patternMatrix.m21()) + " " + ToStr(patternMatrix.m22()) + " " + ToStr(patternMatrix.dx()) + " " + ToStr(patternMatrix.dy()) + "] makepattern setpattern\n");
2890 	PutStream("stroke\n");
2891 }
2892 
HandleMeshGradient(PageItem * item)2893 void PSLib::HandleMeshGradient(PageItem* item)
2894 {
2895 	QString hs,ss,vs,ks;
2896 	double ch,cs,cv,ck;
2897 	QStringList cols;
2898 	QStringList colorValues;
2899 	QStringList spotColorSet;
2900 	QStringList tmpAddedColors;
2901 	tmpAddedColors.clear();
2902 	QList<int> colsSh;
2903 	for (int grow = 0; grow < item->meshGradientArray.count(); grow++)
2904 	{
2905 		for (int gcol = 0; gcol < item->meshGradientArray[grow].count(); gcol++)
2906 		{
2907 			MeshPoint mp1 = item->meshGradientArray[grow][gcol];
2908 			cols.append(mp1.colorName);
2909 			if (!m_Doc->PageColors.contains(mp1.colorName))
2910 			{
2911 				if (!tmpAddedColors.contains(mp1.colorName))
2912 				{
2913 					tmpAddedColors.append(mp1.colorName);
2914 					ScColor tmp;
2915 					tmp.setSpotColor(false);
2916 					tmp.setRegistrationColor(false);
2917 					tmp.fromQColor(mp1.color);
2918 					m_Doc->PageColors.insert(mp1.colorName, tmp);
2919 				}
2920 			}
2921 			colsSh.append(mp1.shade);
2922 			if (spotMap.contains(mp1.colorName))
2923 			{
2924 				if (!spotColorSet.contains(mp1.colorName))
2925 					spotColorSet.append(mp1.colorName);
2926 			}
2927 		}
2928 	}
2929 	for (int ac = 0; ac < cols.count(); ac++)
2930 	{
2931 		QString colorVal = "";
2932 		if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)) && (!GraySc))
2933 		{
2934 			if (spotColorSet.contains(cols.at(ac)))
2935 			{
2936 				colorVal = "0 0 0 0";
2937 				for (int sc = 0; sc < spotColorSet.count(); sc++)
2938 				{
2939 					if (spotColorSet.at(sc) == cols.at(ac))
2940 						colorVal += " " + ToStr(colsSh[ac] / 100.0);
2941 					else
2942 						colorVal += " 0";
2943 				}
2944 			}
2945 			else
2946 			{
2947 				SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
2948 				colorVal += hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
2949 				for (int sc = 0; sc < spotColorSet.count(); sc++)
2950 				{
2951 					colorVal += " 0";
2952 				}
2953 			}
2954 			colorValues.append(colorVal);
2955 		}
2956 		else
2957 		{
2958 			SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
2959 			if (GraySc)
2960 				colorVal += hs.setNum(1.0 - qMin(0.3 * ch + 0.59 * cs + 0.11 * cv + ck, 1.0));
2961 			else
2962 				colorVal += hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
2963 			if (DoSep)
2964 			{
2965 				int pla = Plate - 1 < 0 ? 3 : Plate - 1;
2966 				QStringList cols2 = colorVal.split(" ", Qt::SkipEmptyParts);
2967 				colorVal = ToStr(1 - ScCLocale::toDoubleC(cols2[pla]));
2968 			}
2969 			colorValues.append(colorVal);
2970 		}
2971 	}
2972 	for (int grow = 0; grow < item->meshGradientArray.count() - 1; grow++)
2973 	{
2974 		PutStream("gs\n");
2975 		PutStream("<<\n");
2976 		PutStream("/PatternType 2\n");
2977 		PutStream("/Shading\n");
2978 		PutStream("<<\n");
2979 		PutStream("/ShadingType 7\n");
2980 		if ((DoSep) || (GraySc))
2981 		{
2982 			PutStream("/ColorSpace /DeviceGray\n");
2983 		}
2984 		else if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)))
2985 		{
2986 			PutStream("/ColorSpace [ /DeviceN [/Cyan /Magenta /Yellow /Black");
2987 			for (int sc = 0; sc < spotColorSet.count(); sc++)
2988 			{
2989 				PutStream(" (" + spotColorSet.at(sc) + ")");
2990 			}
2991 			PutStream("]\n");
2992 			PutStream("/DeviceCMYK\n");
2993 			PutStream("{\n");
2994 			int maxSp = spotColorSet.count() - 1;
2995 			for (int sc = 0; sc < spotColorSet.count(); sc++)
2996 			{
2997 				double cc(0), mc(0), yc(0), kc(0);
2998 				CMYKColorF cmykValues;
2999 				ScColorEngine::getCMYKValues(m_Doc->PageColors[spotColorSet.at(maxSp - sc)], m_Doc, cmykValues);
3000 				cmykValues.getValues(cc, mc, yc, kc);
3001 				if (sc == 0)
3002 					PutStream("dup " + ToStr(cc) + " mul ");
3003 				else
3004 					PutStream(IToStr(sc * 4 + 1) + " -1 roll dup " + ToStr(cc) + " mul ");
3005 				PutStream("exch dup " + ToStr(mc) + " mul ");
3006 				PutStream("exch dup " + ToStr(yc) + " mul ");
3007 				PutStream("exch " + ToStr(kc) + " mul\n");
3008 			}
3009 			for (int sc = 0; sc < spotColorSet.count(); sc++)
3010 			{
3011 				PutStream("8 -1 roll 5 -1 roll add 7 -1 roll 5 -1 roll add 6 -1 roll 5 -1 roll add 5 -1 roll 5 -1 roll add\n");
3012 			}
3013 			PutStream("} ]\n");
3014 		}
3015 		else
3016 		{
3017 			PutStream("/ColorSpace /DeviceCMYK\n");
3018 		}
3019 		PutStream("/DataSource [\n");
3020 		QString vertStream;
3021 		QTextStream vst(&vertStream, QIODevice::WriteOnly);
3022 		quint8 flg = 0;
3023 		for (int gcol = 0; gcol < item->meshGradientArray[grow].count() - 1; gcol++)
3024 		{
3025 			MeshPoint mp1 = item->meshGradientArray[grow][gcol];
3026 			MeshPoint mp2 = item->meshGradientArray[grow][gcol+1];
3027 			MeshPoint mp3 = item->meshGradientArray[grow+1][gcol+1];
3028 			MeshPoint mp4 = item->meshGradientArray[grow+1][gcol];
3029 			int colInd1 = grow * item->meshGradientArray[grow].count() + gcol;
3030 			int colInd2 = grow * item->meshGradientArray[grow].count() + gcol + 1;
3031 			int colInd3 = (grow + 1) * item->meshGradientArray[grow].count() + gcol + 1;
3032 			int colInd4 = (grow + 1) * item->meshGradientArray[grow].count() + gcol;
3033 			vst << flg << "\n";
3034 			vst << mp4.gridPoint.x() << " " << -mp4.gridPoint.y() << " " << mp4.controlTop.x() << " " << -mp4.controlTop.y() << " " << mp1.controlBottom.x() << " " << -mp1.controlBottom.y() << "\n";
3035 			vst << mp1.gridPoint.x() << " " << -mp1.gridPoint.y() << " " << mp1.controlRight.x() << " " << -mp1.controlRight.y() << " " << mp2.controlLeft.x() << " " << -mp2.controlLeft.y() << "\n";
3036 			vst << mp2.gridPoint.x() << " " << -mp2.gridPoint.y() << " " << mp2.controlBottom.x() << " " << -mp2.controlBottom.y() << " " << mp3.controlTop.x() << " " << -mp3.controlTop.y() << "\n";
3037 			vst << mp3.gridPoint.x() << " " << -mp3.gridPoint.y() << " " << mp3.controlLeft.x() << " " << -mp3.controlLeft.y() << " " << mp4.controlRight.x() << " " << -mp4.controlRight.y() << "\n";
3038 			vst << mp4.controlColor.x() << " " << -mp4.controlColor.y() << "\n";
3039 			vst << mp1.controlColor.x() << " " << -mp1.controlColor.y() << "\n";
3040 			vst << mp2.controlColor.x() << " " << -mp2.controlColor.y() << "\n";
3041 			vst << mp3.controlColor.x() << " " << -mp3.controlColor.y() << "\n";
3042 			vst << colorValues[colInd4] << " " << colorValues[colInd1] << " " << colorValues[colInd2] << " " << colorValues[colInd3] << "\n";
3043 		}
3044 		PutStream(vertStream);
3045 		PutStream("]\n");
3046 		PutStream(">>\n");
3047 		PutStream(">>\n");
3048 		PutStream("[1 0 0 1 0 0] makepattern\n");
3049 		PutStream("setpattern\n");
3050 		if (fillRule)
3051 			PutStream("eofill\n");
3052 		else
3053 			PutStream("fill\n");
3054 		PutStream("gr\n");
3055 	}
3056 	PS_newpath();
3057 	if (tmpAddedColors.count() != 0)
3058 	{
3059 		for (int cd = 0; cd < tmpAddedColors.count(); cd++)
3060 		{
3061 			m_Doc->PageColors.remove(tmpAddedColors[cd]);
3062 		}
3063 	}
3064 }
3065 
HandlePatchMeshGradient(PageItem * item)3066 void PSLib::HandlePatchMeshGradient(PageItem* item)
3067 {
3068 	QString hs,ss,vs,ks;
3069 	double ch,cs,cv,ck;
3070 	QStringList cols;
3071 	QStringList colorValues;
3072 	QStringList spotColorSet;
3073 	QList<int> colsSh;
3074 	for (int col = 0; col < item->meshGradientPatches.count(); col++)
3075 	{
3076 		meshGradientPatch patch = item->meshGradientPatches[col];
3077 		MeshPoint mp1 = patch.TL;
3078 		cols.append(mp1.colorName);
3079 		colsSh.append(mp1.shade);
3080 		if (spotMap.contains(mp1.colorName))
3081 		{
3082 			if (!spotColorSet.contains(mp1.colorName))
3083 				spotColorSet.append(mp1.colorName);
3084 		}
3085 		MeshPoint mp2 = patch.TR;
3086 		cols.append(mp2.colorName);
3087 		colsSh.append(mp2.shade);
3088 		if (spotMap.contains(mp2.colorName))
3089 		{
3090 			if (!spotColorSet.contains(mp2.colorName))
3091 				spotColorSet.append(mp2.colorName);
3092 		}
3093 		MeshPoint mp3 = patch.BR;
3094 		cols.append(mp3.colorName);
3095 		colsSh.append(mp3.shade);
3096 		if (spotMap.contains(mp3.colorName))
3097 		{
3098 			if (!spotColorSet.contains(mp3.colorName))
3099 				spotColorSet.append(mp3.colorName);
3100 		}
3101 		MeshPoint mp4 = patch.BL;
3102 		cols.append(mp4.colorName);
3103 		colsSh.append(mp4.shade);
3104 		if (spotMap.contains(mp4.colorName))
3105 		{
3106 			if (!spotColorSet.contains(mp4.colorName))
3107 				spotColorSet.append(mp4.colorName);
3108 		}
3109 	}
3110 	for (int ac = 0; ac < cols.count(); ac++)
3111 	{
3112 		QString colorVal = "";
3113 		if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)) && (!GraySc))
3114 		{
3115 			if (spotColorSet.contains(cols.at(ac)))
3116 			{
3117 				colorVal = "0 0 0 0";
3118 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3119 				{
3120 					if (spotColorSet.at(sc) == cols.at(ac))
3121 						colorVal += " " + ToStr(colsSh[ac] / 100.0);
3122 					else
3123 						colorVal += " 0";
3124 				}
3125 			}
3126 			else
3127 			{
3128 				SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
3129 				colorVal += hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3130 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3131 				{
3132 					colorVal += " 0";
3133 				}
3134 			}
3135 			colorValues.append(colorVal);
3136 		}
3137 		else
3138 		{
3139 			SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
3140 			if (GraySc)
3141 				colorVal += hs.setNum(1.0 - qMin(0.3 * ch + 0.59 * cs + 0.11 * cv + ck, 1.0));
3142 			else
3143 				colorVal += hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3144 			if (DoSep)
3145 			{
3146 				int pla = Plate - 1 < 0 ? 3 : Plate - 1;
3147 				QStringList cols2 = colorVal.split(" ", Qt::SkipEmptyParts);
3148 				colorVal = ToStr(1 - ScCLocale::toDoubleC(cols2[pla]));
3149 			}
3150 			colorValues.append(colorVal);
3151 		}
3152 	}
3153 	for (int col = 0; col < item->meshGradientPatches.count(); col++)
3154 	{
3155 		PutStream("gs\n");
3156 		PutStream("<<\n");
3157 		PutStream("/PatternType 2\n");
3158 		PutStream("/Shading\n");
3159 		PutStream("<<\n");
3160 		PutStream("/ShadingType 7\n");
3161 		if ((DoSep) || (GraySc))
3162 		{
3163 			PutStream("/ColorSpace /DeviceGray\n");
3164 		}
3165 		else if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)))
3166 		{
3167 			PutStream("/ColorSpace [ /DeviceN [/Cyan /Magenta /Yellow /Black");
3168 			for (int sc = 0; sc < spotColorSet.count(); sc++)
3169 			{
3170 				PutStream(" (" + spotColorSet.at(sc) + ")");
3171 			}
3172 			PutStream("]\n");
3173 			PutStream("/DeviceCMYK\n");
3174 			PutStream("{\n");
3175 			int maxSp = spotColorSet.count() - 1;
3176 			for (int sc = 0; sc < spotColorSet.count(); sc++)
3177 			{
3178 				double cc(0), mc(0), yc(0), kc(0);
3179 				CMYKColorF cmykValues;
3180 				ScColorEngine::getCMYKValues(m_Doc->PageColors[spotColorSet.at(maxSp - sc)], m_Doc, cmykValues);
3181 				cmykValues.getValues(cc, mc, yc, kc);
3182 				if (sc == 0)
3183 					PutStream("dup " + ToStr(cc) + " mul ");
3184 				else
3185 					PutStream(IToStr(sc * 4 + 1) + " -1 roll dup " + ToStr(cc) + " mul ");
3186 				PutStream("exch dup " + ToStr(mc) + " mul ");
3187 				PutStream("exch dup " + ToStr(yc) + " mul ");
3188 				PutStream("exch " + ToStr(kc) + " mul\n");
3189 			}
3190 			for (int sc = 0; sc < spotColorSet.count(); sc++)
3191 			{
3192 				PutStream("8 -1 roll 5 -1 roll add 7 -1 roll 5 -1 roll add 6 -1 roll 5 -1 roll add 5 -1 roll 5 -1 roll add\n");
3193 			}
3194 			PutStream("} ]\n");
3195 		}
3196 		else
3197 		{
3198 			PutStream("/ColorSpace /DeviceCMYK\n");
3199 		}
3200 		PutStream("/DataSource [\n");
3201 		QString vertStream;
3202 		QTextStream vst(&vertStream, QIODevice::WriteOnly);
3203 		quint8 flg = 0;
3204 		for (int col2 = col; col2 < item->meshGradientPatches.count(); col2++)
3205 		{
3206 			col = col2;
3207 			meshGradientPatch patch = item->meshGradientPatches[col2];
3208 			MeshPoint mp1 = patch.TL;
3209 			MeshPoint mp2 = patch.TR;
3210 			MeshPoint mp3 = patch.BR;
3211 			MeshPoint mp4 = patch.BL;
3212 			int colInd1 = 4 * col2;
3213 			int colInd2 = 4 * col2 + 1;
3214 			int colInd3 = 4 * col2 + 2;
3215 			int colInd4 = 4 * col2 + 3;
3216 			vst << flg << "\n";
3217 			vst << mp4.gridPoint.x() << " " << -mp4.gridPoint.y() << " " << mp4.controlTop.x() << " " << -mp4.controlTop.y() << " " << mp1.controlBottom.x() << " " << -mp1.controlBottom.y() << "\n";
3218 			vst << mp1.gridPoint.x() << " " << -mp1.gridPoint.y() << " " << mp1.controlRight.x() << " " << -mp1.controlRight.y() << " " << mp2.controlLeft.x() << " " << -mp2.controlLeft.y() << "\n";
3219 			vst << mp2.gridPoint.x() << " " << -mp2.gridPoint.y() << " " << mp2.controlBottom.x() << " " << -mp2.controlBottom.y() << " " << mp3.controlTop.x() << " " << -mp3.controlTop.y() << "\n";
3220 			vst << mp3.gridPoint.x() << " " << -mp3.gridPoint.y() << " " << mp3.controlLeft.x() << " " << -mp3.controlLeft.y() << " " << mp4.controlRight.x() << " " << -mp4.controlRight.y() << "\n";
3221 			vst << mp4.controlColor.x() << " " << -mp4.controlColor.y() << "\n";
3222 			vst << mp1.controlColor.x() << " " << -mp1.controlColor.y() << "\n";
3223 			vst << mp2.controlColor.x() << " " << -mp2.controlColor.y() << "\n";
3224 			vst << mp3.controlColor.x() << " " << -mp3.controlColor.y() << "\n";
3225 			vst << colorValues[colInd4] << " " << colorValues[colInd1] << " " << colorValues[colInd2] << " " << colorValues[colInd3] << "\n";
3226 			if ((col % 1000) == 0)
3227 			{
3228 				break;
3229 			}
3230 		}
3231 		PutStream(vertStream);
3232 		PutStream("]\n");
3233 		PutStream(">>\n");
3234 		PutStream(">>\n");
3235 		PutStream("[1 0 0 1 0 0] makepattern\n");
3236 		PutStream("setpattern\n");
3237 		if (fillRule)
3238 			PutStream("eofill\n");
3239 		else
3240 			PutStream("fill\n");
3241 		PutStream("gr\n");
3242 	}
3243 	PS_newpath();
3244 }
3245 
HandleDiamondGradient(PageItem * item)3246 void PSLib::HandleDiamondGradient(PageItem* item)
3247 {
3248 	QString hs,ss,vs,ks;
3249 	double ch,cs,cv,ck;
3250 	QStringList cols;
3251 	QStringList colorValues;
3252 	QStringList spotColorSet;
3253 	QList<int> colsSh;
3254 	VGradient gradient;
3255 	if (!(item->gradient().isEmpty()) && (m_Doc->docGradients.contains(item->gradient())))
3256 		gradient = m_Doc->docGradients[item->gradient()];
3257 	else
3258 		gradient = item->fill_gradient;
3259 	gradient.setRepeatMethod(item->getGradientExtend());
3260 	QList<VColorStop*> colorStops = gradient.colorStops();
3261 	QList<double> qStopRampPoints;
3262 	for (int cst = 0; cst < gradient.stops(); ++cst)
3263 	{
3264 		if (cst == 0)
3265 		{
3266 			if (colorStops[cst]->rampPoint > 0)
3267 			{
3268 				qStopRampPoints.append(0);
3269 				cols.append(colorStops.at(cst)->name);
3270 				colsSh.append(colorStops.at(cst)->shade);
3271 				if (spotMap.contains(colorStops.at(cst)->name))
3272 				{
3273 					if (!spotColorSet.contains(colorStops.at(cst)->name))
3274 						spotColorSet.append(colorStops.at(cst)->name);
3275 				}
3276 			}
3277 		}
3278 		cols.append(colorStops.at(cst)->name);
3279 		colsSh.append(colorStops.at(cst)->shade);
3280 		if (spotMap.contains(colorStops.at(cst)->name))
3281 		{
3282 			if (!spotColorSet.contains(colorStops.at(cst)->name))
3283 				spotColorSet.append(colorStops.at(cst)->name);
3284 		}
3285 		qStopRampPoints.append(colorStops.at(cst)->rampPoint);
3286 	}
3287 	for (int ac = 0; ac < cols.count(); ac++)
3288 	{
3289 		QString colorVal = "";
3290 		if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)) && (!GraySc))
3291 		{
3292 			if (spotColorSet.contains(cols.at(ac)))
3293 			{
3294 				colorVal = "0 0 0 0";
3295 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3296 				{
3297 					if (spotColorSet.at(sc) == cols.at(ac))
3298 						colorVal += " " + ToStr(colsSh[ac] / 100.0);
3299 					else
3300 						colorVal += " 0";
3301 				}
3302 			}
3303 			else
3304 			{
3305 				SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
3306 				colorVal += hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3307 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3308 				{
3309 					colorVal += " 0";
3310 				}
3311 			}
3312 			colorValues.append(colorVal);
3313 		}
3314 		else
3315 		{
3316 			SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
3317 			if (GraySc)
3318 				colorVal += hs.setNum(1.0 - qMin(0.3 * ch + 0.59 * cs + 0.11 * cv + ck, 1.0));
3319 			else
3320 				colorVal += hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3321 			if (DoSep)
3322 			{
3323 				int pla = Plate - 1 < 0 ? 3 : Plate - 1;
3324 				QStringList cols2 = colorVal.split(" ", Qt::SkipEmptyParts);
3325 				colorVal = ToStr(1 - ScCLocale::toDoubleC(cols2[pla]));
3326 			}
3327 			colorValues.append(colorVal);
3328 		}
3329 	}
3330 	PutStream("<<\n");
3331 	PutStream("/PatternType 2\n");
3332 	PutStream("/Shading\n");
3333 	PutStream("<<\n");
3334 	PutStream("/ShadingType 6\n");
3335 	if ((DoSep) || (GraySc))
3336 		PutStream("/ColorSpace /DeviceGray\n");
3337 	else if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)))
3338 	{
3339 		PutStream("/ColorSpace [ /DeviceN [/Cyan /Magenta /Yellow /Black");
3340 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3341 		{
3342 			PutStream(" (" + spotColorSet.at(sc) + ")");
3343 		}
3344 		PutStream("]\n");
3345 		PutStream("/DeviceCMYK\n");
3346 		PutStream("{\n");
3347 		int maxSp = spotColorSet.count() - 1;
3348 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3349 		{
3350 			double cc(0), mc(0), yc(0), kc(0);
3351 			CMYKColorF cmykValues;
3352 			ScColorEngine::getCMYKValues(m_Doc->PageColors[spotColorSet.at(maxSp - sc)], m_Doc, cmykValues);
3353 			cmykValues.getValues(cc, mc, yc, kc);
3354 			if (sc == 0)
3355 				PutStream("dup " + ToStr(cc) + " mul ");
3356 			else
3357 				PutStream(IToStr(sc * 4 + 1) + " -1 roll dup " + ToStr(cc) + " mul ");
3358 			PutStream("exch dup " + ToStr(mc) + " mul ");
3359 			PutStream("exch dup " + ToStr(yc) + " mul ");
3360 			PutStream("exch " + ToStr(kc) + " mul\n");
3361 		}
3362 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3363 		{
3364 			PutStream("8 -1 roll 5 -1 roll add 7 -1 roll 5 -1 roll add 6 -1 roll 5 -1 roll add 5 -1 roll 5 -1 roll add\n");
3365 		}
3366 		PutStream("} ]\n");
3367 	}
3368 	else
3369 		PutStream("/ColorSpace /DeviceCMYK\n");
3370 	PutStream("/Background [" + colorValues[colorValues.count() - 1] + "]\n");
3371 	PutStream("/DataSource [\n");
3372 	QPointF centerP = QPointF(item->GrControl5.x(), -item->GrControl5.y());
3373 	QLineF edge1 = QLineF(centerP, QPointF(item->GrControl1.x(), -item->GrControl1.y()));
3374 	QLineF edge2 = QLineF(centerP, QPointF(item->GrControl2.x(), -item->GrControl2.y()));
3375 	QLineF edge3 = QLineF(centerP, QPointF(item->GrControl3.x(), -item->GrControl3.y()));
3376 	QLineF edge4 = QLineF(centerP, QPointF(item->GrControl4.x(), -item->GrControl4.y()));
3377 	for (int offset = 1; offset < qStopRampPoints.count(); ++offset)
3378 	{
3379 		QLineF e1 = edge1;
3380 		QLineF e1s = edge1;
3381 		QLineF e2 = edge2;
3382 		QLineF e2s = edge2;
3383 		QLineF e3 = edge3;
3384 		QLineF e3s = edge3;
3385 		QLineF e4 = edge4;
3386 		QLineF e4s = edge4;
3387 		e1.setLength(edge1.length() * qStopRampPoints[ offset ]);
3388 		e2.setLength(edge2.length() * qStopRampPoints[ offset ]);
3389 		e3.setLength(edge3.length() * qStopRampPoints[ offset ]);
3390 		e4.setLength(edge4.length() * qStopRampPoints[ offset ]);
3391 		e1s.setLength(edge1.length() * qStopRampPoints[ offset - 1 ]);
3392 		e2s.setLength(edge2.length() * qStopRampPoints[ offset - 1 ]);
3393 		e3s.setLength(edge3.length() * qStopRampPoints[ offset - 1 ]);
3394 		e4s.setLength(edge4.length() * qStopRampPoints[ offset - 1 ]);
3395 		if (offset == 1)
3396 		{
3397 			PutStream("0\n");
3398 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + "\n");
3399 			PutStream(ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + "\n");
3400 			PutStream(ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3401 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3402 			PutStream(colorValues[0] + " " + colorValues[1] + " " + colorValues[1] + " " + colorValues[0] + "\n");
3403 			PutStream("0\n");
3404 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3405 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + "\n");
3406 			PutStream(ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + "\n");
3407 			PutStream(ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3408 			PutStream(colorValues[0] + " " + colorValues[0] + " " + colorValues[1] + " " + colorValues[1] + "\n");
3409 			PutStream("0\n");
3410 			PutStream(ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3411 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3412 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + "\n");
3413 			PutStream(ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + "\n");
3414 			PutStream(colorValues[1] + " " + colorValues[0] + " " + colorValues[0] + " " + colorValues[1] + "\n");
3415 			PutStream("0\n");
3416 			PutStream(ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + "\n");
3417 			PutStream(ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3418 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + "\n");
3419 			PutStream(ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(centerP.x()) + " " + ToStr(centerP.y()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + "\n");
3420 			PutStream(colorValues[1] + " " + colorValues[1] + " " + colorValues[0] + " " + colorValues[0] + "\n");
3421 		}
3422 		else
3423 		{
3424 			PutStream("0\n");
3425 			PutStream(ToStr(e1s.x2()) + " " + ToStr(e1s.y2()) + " " + ToStr(e1s.x2()) + " " + ToStr(e1s.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + "\n");
3426 			PutStream(ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + "\n");
3427 			PutStream(ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e2s.x2()) + " " + ToStr(e2s.y2()) + "\n");
3428 			PutStream(ToStr(e2s.x2()) + " " + ToStr(e2s.y2()) + " " + ToStr(e2s.x2()) + " " + ToStr(e2s.y2()) + " " + ToStr(e1s.x2()) + " " + ToStr(e1s.y2()) + "\n");
3429 			PutStream(colorValues[offset - 1] + " " + colorValues[offset] + " " + colorValues[offset] + " " + colorValues[offset - 1] + "\n");
3430 			PutStream("0\n");
3431 			PutStream(ToStr(e3s.x2()) + " " + ToStr(e3s.y2()) + " " + ToStr(e3s.x2()) + " " + ToStr(e3s.y2()) + " " + ToStr(e2s.x2()) + " " + ToStr(e2s.y2()) + "\n");
3432 			PutStream(ToStr(e2s.x2()) + " " + ToStr(e2s.y2()) + " " + ToStr(e2s.x2()) + " " + ToStr(e2s.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + "\n");
3433 			PutStream(ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e2.x2()) + " " + ToStr(e2.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + "\n");
3434 			PutStream(ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e3s.x2()) + " " + ToStr(e3s.y2()) + "\n");
3435 			PutStream(colorValues[offset - 1] + " " + colorValues[offset - 1] + " " + colorValues[offset] + " " + colorValues[offset] + "\n");
3436 			PutStream("0\n");
3437 			PutStream(ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e4s.x2()) + " " + ToStr(e4s.y2()) + "\n");
3438 			PutStream(ToStr(e4s.x2()) + " " + ToStr(e4s.y2()) + " " + ToStr(e4s.x2()) + " " + ToStr(e4s.y2()) + " " + ToStr(e3s.x2()) + " " + ToStr(e3s.y2()) + "\n");
3439 			PutStream(ToStr(e3s.x2()) + " " + ToStr(e3s.y2()) + " " + ToStr(e3s.x2()) + " " + ToStr(e3s.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + "\n");
3440 			PutStream(ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e3.x2()) + " " + ToStr(e3.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + "\n");
3441 			PutStream(colorValues[offset] + " " + colorValues[offset - 1] + " " + colorValues[offset - 1] + " " + colorValues[offset] + "\n");
3442 			PutStream("0\n");
3443 			PutStream(ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + "\n");
3444 			PutStream(ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e1.x2()) + " " + ToStr(e1.y2()) + " " + ToStr(e1s.x2()) + " " + ToStr(e1s.y2()) + "\n");
3445 			PutStream(ToStr(e1s.x2()) + " " + ToStr(e1s.y2()) + " " + ToStr(e1s.x2()) + " " + ToStr(e1s.y2()) + " " + ToStr(e4s.x2()) + " " + ToStr(e4s.y2()) + "\n");
3446 			PutStream(ToStr(e4s.x2()) + " " + ToStr(e4s.y2()) + " " + ToStr(e4s.x2()) + " " + ToStr(e4s.y2()) + " " + ToStr(e4.x2()) + " " + ToStr(e4.y2()) + "\n");
3447 			PutStream(colorValues[offset] + " " + colorValues[offset] + " " + colorValues[offset - 1] + " " + colorValues[offset - 1] + "\n");
3448 		}
3449 	}
3450 	PutStream("]\n");
3451 	PutStream(">>\n");
3452 	PutStream(">>\n");
3453 	PutStream("[1 0 0 1 0 0] makepattern setpattern\n");
3454 	if (fillRule)
3455 		PutStream("eofill\n");
3456 	else
3457 		PutStream("fill\n");
3458 }
3459 
HandleTensorGradient(PageItem * item)3460 void PSLib::HandleTensorGradient(PageItem* item)
3461 {
3462 	QString GCol;
3463 	QString hs,ss,vs,ks;
3464 	double ch,cs,cv,ck;
3465 	QStringList cols;
3466 	QStringList spotColorSet;
3467 	QList<int> colsSh;
3468 	cols << item->GrColorP4 << item->GrColorP1 << item->GrColorP2 << item->GrColorP3;
3469 	colsSh << item->GrCol4Shade << item->GrCol1Shade << item->GrCol2Shade << item->GrCol3Shade;
3470 	for (int cst = 0; cst < cols.count(); ++cst)
3471 	{
3472 		if (spotMap.contains(cols.at(cst)))
3473 		{
3474 			if (!spotColorSet.contains(cols.at(cst)))
3475 				spotColorSet.append(cols.at(cst));
3476 		}
3477 	}
3478 	PutStream("<<\n");
3479 	PutStream("/PatternType 2\n");
3480 	PutStream("/Shading\n");
3481 	PutStream("<<\n");
3482 	PutStream("/ShadingType 7\n");
3483 	if ((DoSep) || (GraySc))
3484 		PutStream("/ColorSpace /DeviceGray\n");
3485 	else if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)))
3486 	{
3487 		PutStream("/ColorSpace [ /DeviceN [/Cyan /Magenta /Yellow /Black");
3488 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3489 		{
3490 			PutStream(" (" + spotColorSet.at(sc) + ")");
3491 		}
3492 		PutStream("]\n");
3493 		PutStream("/DeviceCMYK\n");
3494 		PutStream("{\n");
3495 		int maxSp = spotColorSet.count() - 1;
3496 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3497 		{
3498 			double cc(0), mc(0), yc(0), kc(0);
3499 			CMYKColorF cmykValues;
3500 			ScColorEngine::getCMYKValues(m_Doc->PageColors[spotColorSet.at(maxSp - sc)], m_Doc, cmykValues);
3501 			cmykValues.getValues(cc, mc, yc, kc);
3502 			if (sc == 0)
3503 				PutStream("dup " + ToStr(cc) + " mul ");
3504 			else
3505 				PutStream(IToStr(sc * 4 + 1) + " -1 roll dup " + ToStr(cc) + " mul ");
3506 			PutStream("exch dup " + ToStr(mc) + " mul ");
3507 			PutStream("exch dup " + ToStr(yc) + " mul ");
3508 			PutStream("exch " + ToStr(kc) + " mul\n");
3509 		}
3510 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3511 		{
3512 			PutStream("8 -1 roll 5 -1 roll add 7 -1 roll 5 -1 roll add 6 -1 roll 5 -1 roll add 5 -1 roll 5 -1 roll add\n");
3513 		}
3514 		PutStream("} ]\n");
3515 	}
3516 	else
3517 		PutStream("/ColorSpace /DeviceCMYK\n");
3518 	PutStream("/DataSource [0\n");
3519 	PutStream("0 " + ToStr(-item->height()) + " 0 " + ToStr(-item->height()) + " 0 0 0 0 0 0 " + ToStr(item->width()) + " 0 " + ToStr(item->width()) + " 0 " + ToStr(item->width()) + " 0\n");
3520 	PutStream(ToStr(item->width()) + " " + ToStr(-item->height()) + " " + ToStr(item->width()) + " " + ToStr(-item->height()) + " " + ToStr(item->width()) + " " + ToStr(-item->height()) + "\n");
3521 	PutStream("0 " + ToStr(-item->height()) + "\n");
3522 	PutStream(ToStr(item->GrControl1.x()) + " " + ToStr(-item->GrControl1.y()) + "\n");
3523 	PutStream(ToStr(item->GrControl4.x()) + " " + ToStr(-item->GrControl4.y()) + "\n");
3524 	PutStream(ToStr(item->GrControl3.x()) + " " + ToStr(-item->GrControl3.y()) + "\n");
3525 	PutStream(ToStr(item->GrControl2.x()) + " " + ToStr(-item->GrControl2.y()) + "\n");
3526 	for (int ac = 0; ac < cols.count(); ac++)
3527 	{
3528 		if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)) && (!GraySc))
3529 		{
3530 			if (spotColorSet.contains(cols.at(ac)))
3531 			{
3532 				PutStream("0 0 0 0");
3533 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3534 				{
3535 					if (spotColorSet.at(sc) == cols.at(ac))
3536 						PutStream(" " + ToStr(colsSh[ac] / 100.0));
3537 					else
3538 						PutStream(" 0");
3539 				}
3540 			}
3541 			else
3542 			{
3543 				SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
3544 				GCol = hs.setNum(ch)  + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3545 				PutStream(GCol);
3546 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3547 				{
3548 					PutStream(" 0");
3549 				}
3550 			}
3551 			PutStream("\n");
3552 		}
3553 		else
3554 		{
3555 			SetColor(cols.at(ac), colsSh.at(ac), &ch, &cs, &cv, &ck);
3556 			if (GraySc)
3557 				GCol = hs.setNum(1.0 - qMin(0.3 * ch + 0.59 * cs + 0.11 * cv + ck, 1.0));
3558 			else
3559 				GCol = hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3560 			if (DoSep)
3561 			{
3562 				int pla = Plate - 1 < 0 ? 3 : Plate - 1;
3563 				QStringList cols2 = GCol.split(" ", Qt::SkipEmptyParts);
3564 				PutStream(ToStr(1 - ScCLocale::toDoubleC(cols2[pla])) + "\n");
3565 			}
3566 			else
3567 				PutStream(GCol + "\n");
3568 		}
3569 	}
3570 	PutStream("]\n");
3571 	PutStream(">>\n");
3572 	PutStream(">>\n");
3573 	PutStream("[1 0 0 1 0 0] makepattern setpattern\n");
3574 	if (fillRule)
3575 		PutStream("eofill\n");
3576 	else
3577 		PutStream("fill\n");
3578 }
3579 
HandleGradientFillStroke(PageItem * item,bool stroke,bool forArrow)3580 void PSLib::HandleGradientFillStroke(PageItem *item, bool stroke, bool forArrow)
3581 {
3582 	double StartX, StartY, EndX, EndY, FocalX, FocalY, Gscale, Gskew;
3583 	int GType;
3584 	VGradient gradient;
3585 	QList<double> StopVec;
3586 	QStringList colorNames;
3587 	QList<int> colorShades;
3588 	QStringList spotColorSet;
3589 	if (stroke)
3590 	{
3591 		GType = item->GrTypeStroke;
3592 		StartX = item->GrStrokeStartX;
3593 		StartY = item->GrStrokeStartY;
3594 		EndX = item->GrStrokeEndX;
3595 		EndY = item->GrStrokeEndY;
3596 		FocalX = item->GrStrokeFocalX;
3597 		FocalY = item->GrStrokeFocalY;
3598 		Gscale = item->GrStrokeScale;
3599 		Gskew = item->GrStrokeSkew;
3600 		if (!(item->strokeGradient().isEmpty()) && (m_Doc->docGradients.contains(item->strokeGradient())))
3601 			gradient = m_Doc->docGradients[item->strokeGradient()];
3602 		else
3603 			gradient = item->stroke_gradient;
3604 		gradient.setRepeatMethod(item->getStrokeGradientExtend());
3605 	}
3606 	else
3607 	{
3608 		GType = item->GrType;
3609 		StartX = item->GrStartX;
3610 		StartY = item->GrStartY;
3611 		EndX = item->GrEndX;
3612 		EndY = item->GrEndY;
3613 		FocalX = item->GrFocalX;
3614 		FocalY = item->GrFocalY;
3615 		Gscale = item->GrScale;
3616 		Gskew = item->GrSkew;
3617 		if (!(item->gradient().isEmpty()) && (m_Doc->docGradients.contains(item->gradient())))
3618 			gradient = m_Doc->docGradients[item->gradient()];
3619 		else
3620 			gradient = item->fill_gradient;
3621 		gradient.setRepeatMethod(item->getGradientExtend());
3622 		if (GType == Gradient_Pattern)
3623 		{
3624 			QTransform patternMatrix;
3625 			double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
3626 			ScPattern *pat = &m_Doc->docPatterns[item->pattern()];
3627 			uint patHash = qHash(item->pattern());
3628 			item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
3629 			patternMatrix.translate(patternOffsetX, -patternOffsetY);
3630 			patternMatrix.rotate(-patternRotation);
3631 			patternMatrix.shear(patternSkewX, -patternSkewY);
3632 			patternMatrix.scale(pat->scaleX, pat->scaleY);
3633 			patternMatrix.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
3634 			bool mirrorX, mirrorY;
3635 			item->patternFlip(mirrorX, mirrorY);
3636 			if (mirrorX)
3637 				patternMatrix.scale(-1, 1);
3638 			if (mirrorY)
3639 				patternMatrix.scale(1, -1);
3640 			PutStream("Pattern" + QString::number(patHash) + " [" + ToStr(patternMatrix.m11()) + " " + ToStr(patternMatrix.m12()) + " " + ToStr(patternMatrix.m21()) + " " + ToStr(patternMatrix.m22()) + " " + ToStr(patternMatrix.dx()) + " " + ToStr(patternMatrix.dy()) + "] makepattern setpattern\n");
3641 			if (fillRule)
3642 				PutStream("eofill\n");
3643 			else
3644 				PutStream("fill\n");
3645 			return;
3646 		}
3647 		if (GType == Gradient_4Colors)
3648 		{
3649 			HandleTensorGradient(item);
3650 			return;
3651 		}
3652 		if (GType == Gradient_Diamond)
3653 		{
3654 			HandleDiamondGradient(item);
3655 			return;
3656 		}
3657 		if ((GType == Gradient_Mesh) || (GType == Gradient_Conical))
3658 		{
3659 			HandleMeshGradient(item);
3660 			return;
3661 		}
3662 		if (GType == Gradient_PatchMesh)
3663 		{
3664 			HandlePatchMeshGradient(item);
3665 			return;
3666 		}
3667 	}
3668 	QList<VColorStop*> cstops = gradient.colorStops();
3669 	PutStream("<<\n");
3670 	PutStream("/PatternType 2\n");
3671 	PutStream("/Shading\n");
3672 	PutStream("<<\n");
3673 	for (int cst = 0; cst < gradient.stops(); ++cst)
3674 	{
3675 		double actualStop = cstops.at(cst)->rampPoint;
3676 		if ((cst == 0) && (actualStop != 0.0))
3677 		{
3678 			StopVec.append(0.0);
3679 			colorNames.append(cstops.at(cst)->name);
3680 			colorShades.append(cstops.at(cst)->shade);
3681 		}
3682 		StopVec.append(actualStop);
3683 		colorNames.append(cstops.at(cst)->name);
3684 		colorShades.append(cstops.at(cst)->shade);
3685 		if (spotMap.contains(cstops.at(cst)->name))
3686 		{
3687 			if (!spotColorSet.contains(cstops.at(cst)->name))
3688 				spotColorSet.append(cstops.at(cst)->name);
3689 		}
3690 		if ((cst == gradient.stops()-1) && (actualStop < 1.0))
3691 		{
3692 			StopVec.append(1.0);
3693 			colorNames.append(cstops.at(cst)->name);
3694 			colorShades.append(cstops.at(cst)->shade);
3695 		}
3696 	}
3697 	if (GType == Gradient_Linear)
3698 		PutStream("/ShadingType 2\n");
3699 	else
3700 		PutStream("/ShadingType 3\n");
3701 	if ((DoSep) || (GraySc))
3702 		PutStream("/ColorSpace /DeviceGray\n");
3703 	else if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)))
3704 	{
3705 		PutStream("/ColorSpace [ /DeviceN [/Cyan /Magenta /Yellow /Black");
3706 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3707 		{
3708 			PutStream(" (" + spotColorSet.at(sc) + ")");
3709 		}
3710 		PutStream("]\n");
3711 		PutStream("/DeviceCMYK\n");
3712 		PutStream("{\n");
3713 		int maxSp = spotColorSet.count() - 1;
3714 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3715 		{
3716 			double cc(0), mc(0), yc(0), kc(0);
3717 			CMYKColorF cmykValues;
3718 			ScColorEngine::getCMYKValues(m_Doc->PageColors[spotColorSet.at(maxSp - sc)], m_Doc, cmykValues);
3719 			cmykValues.getValues(cc, mc, yc, kc);
3720 			if (sc == 0)
3721 				PutStream("dup " + ToStr(cc) + " mul ");
3722 			else
3723 				PutStream(IToStr(sc * 4 + 1) + " -1 roll dup " + ToStr(cc) + " mul ");
3724 			PutStream("exch dup " + ToStr(mc) + " mul ");
3725 			PutStream("exch dup " + ToStr(yc) + " mul ");
3726 			PutStream("exch " + ToStr(kc) + " mul\n");
3727 		}
3728 		for (int sc = 0; sc < spotColorSet.count(); sc++)
3729 		{
3730 			PutStream("8 -1 roll 5 -1 roll add 7 -1 roll 5 -1 roll add 6 -1 roll 5 -1 roll add 5 -1 roll 5 -1 roll add\n");
3731 		}
3732 		PutStream("} ]\n");
3733 	}
3734 	else
3735 		PutStream("/ColorSpace /DeviceCMYK\n");
3736 	if (gradient.repeatMethod() == VGradient::none)
3737 		PutStream("/Extend [false false]\n");
3738 	else
3739 		PutStream("/Extend [true true]\n");
3740 	if (GType == Gradient_Linear)
3741 		PutStream("/Coords [" + ToStr(StartX) + " " + ToStr(-StartY) + " " + ToStr(EndX) + " " + ToStr(-EndY) + "]\n");
3742 	else
3743 		PutStream("/Coords [" + ToStr(FocalX) + " " + ToStr(-FocalY) + " 0.0 " + ToStr(StartX) + " " + ToStr(-StartY) + " " + ToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2))) + "]\n");
3744 	PutStream("/Function\n");
3745 	PutStream("<<\n");
3746 	PutStream("/FunctionType 3\n");
3747 	PutStream("/Domain [0 1]\n");
3748 	if (StopVec.count() > 2)
3749 	{
3750 		PutStream("/Bounds [");
3751 		QString bctx = "";
3752 		for (int bc = 1; bc < StopVec.count() - 1; bc++)
3753 		{
3754 			bctx += ToStr(StopVec.at(bc)) + " ";
3755 		}
3756 		PutStream(bctx.trimmed() + "]\n");
3757 	}
3758 	else
3759 		PutStream("/Bounds []\n");
3760 	QString entx = "";
3761 	PutStream("/Functions\n");
3762 	PutStream("[\n");
3763 	for (int cc = 0; cc < colorNames.count() - 1; cc++)
3764 	{
3765 		QString GCol, GCol2;
3766 		QString hs,ss,vs,ks;
3767 		double ch,cs,cv,ck;
3768 		entx += "0 1 ";
3769 		PutStream("<<\n");
3770 		PutStream("/FunctionType 2\n");
3771 		PutStream("/Domain [0 1]\n");
3772 		if ((Options.useSpotColors) && ((spotColorSet.count() > 0) && (spotColorSet.count() < 28)) && (!GraySc))
3773 		{
3774 			if (spotColorSet.contains(colorNames.at(cc)))
3775 			{
3776 				PutStream("/C0 [0 0 0 0");
3777 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3778 				{
3779 					if (spotColorSet.at(sc) == colorNames.at(cc))
3780 						PutStream(" " + ToStr(colorShades[cc] / 100.0));
3781 					else
3782 						PutStream(" 0");
3783 				}
3784 			}
3785 			else
3786 			{
3787 				SetColor(colorNames.at(cc), colorShades.at(cc), &ch, &cs, &cv, &ck);
3788 				GCol = hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3789 				PutStream("/C0 [" + GCol);
3790 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3791 				{
3792 					PutStream(" 0");
3793 				}
3794 			}
3795 			PutStream("]\n");
3796 			if (spotColorSet.contains(colorNames.at(cc+1)))
3797 			{
3798 				PutStream("/C1 [0 0 0 0");
3799 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3800 				{
3801 					if (spotColorSet.at(sc) == colorNames.at(cc+1))
3802 						PutStream(" " + ToStr(colorShades[cc+1] / 100.0));
3803 					else
3804 						PutStream(" 0");
3805 				}
3806 			}
3807 			else
3808 			{
3809 				SetColor(colorNames.at(cc+1), colorShades.at(cc+1), &ch, &cs, &cv, &ck);
3810 				GCol2 = hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3811 				PutStream("/C1 [" + GCol2);
3812 				for (int sc = 0; sc < spotColorSet.count(); sc++)
3813 				{
3814 					PutStream(" 0");
3815 				}
3816 			}
3817 			PutStream("]\n");
3818 		}
3819 		else
3820 		{
3821 			SetColor(colorNames.at(cc), colorShades.at(cc), &ch, &cs, &cv, &ck);
3822 			if (GraySc)
3823 				GCol = hs.setNum(1.0 - qMin(0.3 * ch + 0.59 * cs + 0.11 * cv + ck, 1.0));
3824 			else
3825 				GCol = hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3826 			SetColor(colorNames.at(cc+1), colorShades.at(cc+1), &ch, &cs, &cv, &ck);
3827 			if (GraySc)
3828 				GCol2 = hs.setNum(1.0 - qMin(0.3 * ch + 0.59 * cs + 0.11 * cv + ck, 1.0));
3829 			else
3830 				GCol2 = hs.setNum(ch) + " " + ss.setNum(cs) + " " + vs.setNum(cv) + " " + ks.setNum(ck);
3831 			if (DoSep)
3832 			{
3833 				int pla = Plate - 1 < 0 ? 3 : Plate - 1;
3834 				QStringList cols1 = GCol.split(" ", Qt::SkipEmptyParts);
3835 				QStringList cols2 = GCol2.split(" ", Qt::SkipEmptyParts);
3836 				PutStream("/C1 [" + ToStr(1 - ScCLocale::toDoubleC(cols1[pla])) + "]\n");
3837 				PutStream("/C0 [" + ToStr(1 - ScCLocale::toDoubleC(cols2[pla])) + "]\n");
3838 			}
3839 			else
3840 			{
3841 				PutStream("/C0 [" + GCol + "]\n");
3842 				PutStream("/C1 [" + GCol2  + "]\n");
3843 			}
3844 		}
3845 		PutStream("/N 1\n");
3846 		PutStream(">>\n");
3847 	}
3848 	PutStream("]\n");
3849 	PutStream("/Encode [" + entx.trimmed() + "]\n");
3850 	PutStream(">>\n");
3851 	PutStream(">>\n");
3852 	PutStream(">>\n");
3853 	QTransform qmatrix;
3854 	if (Gskew == 90)
3855 		Gskew = 1;
3856 	else if (Gskew == 180)
3857 		Gskew = 0;
3858 	else if (Gskew == 270)
3859 		Gskew = -1;
3860 	else if (Gskew == 390)
3861 		Gskew = 0;
3862 	else
3863 		Gskew = tan(M_PI / 180.0 * Gskew);
3864 	if (GType == Gradient_Linear)
3865 	{
3866 		qmatrix.translate(StartX, -StartY);
3867 		qmatrix.shear(Gskew, 0);
3868 		qmatrix.translate(-StartX, StartY);
3869 	}
3870 	else
3871 	{
3872 		double rotEnd = xy2Deg(EndX - StartX, EndY - StartY);
3873 		qmatrix.translate(StartX, -StartY);
3874 		qmatrix.rotate(-rotEnd);
3875 		qmatrix.shear(-Gskew, 0);
3876 		qmatrix.translate(0, -StartY * (1.0 - Gscale));
3877 		qmatrix.translate(-StartX, StartY);
3878 		qmatrix.scale(1, Gscale);
3879 	}
3880 	PutStream("[" + ToStr(qmatrix.m11()) + " " + ToStr(qmatrix.m12()) + " " + ToStr(qmatrix.m21()) + " " + ToStr(qmatrix.m22()) + " " + ToStr(qmatrix.dx()) + " " + ToStr(qmatrix.dy()) + "] makepattern setpattern\n");
3881 //	PutStream("[1 0 0 1 0 0] makepattern setpattern\n");
3882 	if (forArrow)
3883 	{
3884 		if (fillRule)
3885 			PutStream("eofill\n");
3886 		else
3887 			PutStream("fill\n");
3888 	}
3889 	else
3890 	{
3891 		if (stroke)
3892 			PutStream("stroke\n");
3893 		else
3894 		{
3895 			if (fillRule)
3896 				PutStream("eofill\n");
3897 			else
3898 				PutStream("fill\n");
3899 		}
3900 	}
3901 }
3902 
PS_HatchFill(PageItem * currItem)3903 void PSLib::PS_HatchFill(PageItem *currItem)
3904 {
3905 	PS_save();
3906 	QVector<double> dum;
3907 	double h, s, v, k;
3908 	PS_setlinewidth(1);
3909 	PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
3910 	PS_setdash(Qt::SolidLine, 0, dum);
3911 	if ((currItem->hatchBackground != CommonStrings::None) && (currItem->hatchUseBackground))
3912 	{
3913 		SetColor(currItem->hatchBackground, 100, &h, &s, &v, &k);
3914 		PS_setcmykcolor_fill(h, s, v, k);
3915 		putColor(currItem->hatchBackground, 100, true);
3916 		SetPathAndClip(currItem->PoLine, currItem->fillRule);
3917 	}
3918 	else
3919 		PS_clip(currItem->fillRule);
3920 	if (currItem->hatchForeground != CommonStrings::None)
3921 	{
3922 		SetColor(currItem->hatchForeground, 100, &h, &s, &v, &k);
3923 		PS_setcmykcolor_stroke(h, s, v, k);
3924 	}
3925 	PS_translate(currItem->width() / 2.0, -currItem->height() / 2.0);
3926 	double lineLen = sqrt((currItem->width() / 2.0) * (currItem->width() / 2.0) + (currItem->height() / 2.0) * (currItem->height() / 2.0));
3927 	double dist = 0.0;
3928 	PS_save();
3929 	PS_rotate(currItem->hatchAngle);
3930 	while (dist < lineLen)
3931 	{
3932 		PS_moveto(-lineLen, dist);
3933 		PS_lineto(lineLen, dist);
3934 		putColor(currItem->hatchForeground, 100, false);
3935 		if (dist > 0)
3936 		{
3937 			PS_moveto(-lineLen, -dist);
3938 			PS_lineto(lineLen, -dist);
3939 			putColor(currItem->hatchForeground, 100, false);
3940 		}
3941 		dist += currItem->hatchDistance;
3942 	}
3943 	PS_restore();
3944 	dist = 0.0;
3945 	if ((currItem->hatchType == 1) || (currItem->hatchType == 2))
3946 	{
3947 		PS_save();
3948 		PS_rotate(currItem->hatchAngle + 90);
3949 		while (dist < lineLen)
3950 		{
3951 			PS_moveto(-lineLen, dist);
3952 			PS_lineto(lineLen, dist);
3953 			putColor(currItem->hatchForeground, 100, false);
3954 			if (dist > 0)
3955 			{
3956 				PS_moveto(-lineLen, -dist);
3957 				PS_lineto(lineLen, -dist);
3958 				putColor(currItem->hatchForeground, 100, false);
3959 			}
3960 			dist += currItem->hatchDistance;
3961 		}
3962 		PS_restore();
3963 	}
3964 	dist = 0.0;
3965 	if (currItem->hatchType == 2)
3966 	{
3967 		PS_save();
3968 		PS_rotate(currItem->hatchAngle - 45);
3969 		while (dist < lineLen)
3970 		{
3971 			PS_moveto(-lineLen, dist * sqrt(2.0));
3972 			PS_lineto(lineLen, dist * sqrt(2.0));
3973 			putColor(currItem->hatchForeground, 100, false);
3974 			if (dist > 0)
3975 			{
3976 				PS_moveto(-lineLen, -dist * sqrt(2.0));
3977 				PS_lineto(lineLen, -dist * sqrt(2.0));
3978 				putColor(currItem->hatchForeground, 100, false);
3979 			}
3980 			dist += currItem->hatchDistance;
3981 		}
3982 		PS_restore();
3983 	}
3984 	PS_restore();
3985 	if (currItem->lineColor() != CommonStrings::None)
3986 	{
3987 		SetColor(currItem->lineColor(), currItem->lineShade(), &h, &s, &v, &k);
3988 		PS_setcmykcolor_stroke(h, s, v, k);
3989 	}
3990 }
3991 
drawArrow(PageItem * ite,QTransform & arrowTrans,int arrowIndex)3992 void PSLib::drawArrow(PageItem *ite, QTransform &arrowTrans, int arrowIndex)
3993 {
3994 	double h, s, v, k;
3995 	QVector<double> dum;
3996 	FPointArray arrow = m_Doc->arrowStyles().at(arrowIndex-1).points.copy();
3997 	if (ite->NamedLStyle.isEmpty())
3998 	{
3999 		if (ite->lineWidth() != 0.0)
4000 			arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
4001 	}
4002 	else
4003 	{
4004 		multiLine ml = m_Doc->docLineStyles[ite->NamedLStyle];
4005 		if (ml[ml.size() - 1].Width != 0.0)
4006 			arrowTrans.scale(ml[ml.size() - 1].Width, ml[ml.size() - 1].Width);
4007 	}
4008 	arrow.map(arrowTrans);
4009 	if (ite->NamedLStyle.isEmpty())
4010 	{
4011 		ScPattern* strokePattern = m_Doc->checkedPattern(ite->strokePattern());
4012 		if (strokePattern)
4013 		{
4014 			PS_newpath();
4015 			SetClipPath(arrow);
4016 			PS_closepath();
4017 			QTransform patternMatrix;
4018 			double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace;
4019 			ScPattern *pat = &m_Doc->docPatterns[ite->strokePattern()];
4020 			uint patHash = qHash(ite->strokePattern());
4021 			ite->strokePatternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace);
4022 			patternMatrix.translate(patternOffsetX, -patternOffsetY);
4023 			patternMatrix.rotate(-patternRotation);
4024 			patternMatrix.shear(patternSkewX, -patternSkewY);
4025 			patternMatrix.scale(pat->scaleX, pat->scaleY);
4026 			patternMatrix.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
4027 			bool mirrorX, mirrorY;
4028 			ite->strokePatternFlip(mirrorX, mirrorY);
4029 			if (mirrorX)
4030 				patternMatrix.scale(-1, 1);
4031 			if (mirrorY)
4032 				patternMatrix.scale(1, -1);
4033 			PutStream("Pattern" + QString::number(patHash) + " [" + ToStr(patternMatrix.m11()) + " " + ToStr(patternMatrix.m12()) + " " + ToStr(patternMatrix.m21()) + " " + ToStr(patternMatrix.m22()) + " " + ToStr(patternMatrix.dx()) + " " + ToStr(patternMatrix.dy()) + "] makepattern setpattern\n");
4034 			if (fillRule)
4035 				PutStream("eofill\n");
4036 			else
4037 				PutStream("fill\n");
4038 		}
4039 		else if (ite->GrTypeStroke > 0)
4040 		{
4041 			PS_newpath();
4042 			SetClipPath(arrow);
4043 			PS_closepath();
4044 			HandleGradientFillStroke(ite, true, true);
4045 		}
4046 		else if (ite->lineColor() != CommonStrings::None)
4047 		{
4048 			SetColor(ite->lineColor(), ite->lineShade(), &h, &s, &v, &k);
4049 			PS_setcmykcolor_fill(h, s, v, k);
4050 			PS_newpath();
4051 			SetClipPath(arrow);
4052 			PS_closepath();
4053 			putColor(ite->lineColor(), ite->lineShade(), true);
4054 		}
4055 	}
4056 	else
4057 	{
4058 		multiLine ml = m_Doc->docLineStyles[ite->NamedLStyle];
4059 		if (ml[0].Color != CommonStrings::None)
4060 		{
4061 			SetColor(ml[0].Color, ml[0].Shade, &h, &s, &v, &k);
4062 			PS_setcmykcolor_fill(h, s, v, k);
4063 			PS_newpath();
4064 			SetClipPath(arrow);
4065 			PS_closepath();
4066 			putColor(ite->lineColor(), ite->lineShade(), true);
4067 		}
4068 		for (int it = ml.size() - 1; it > 0; it--)
4069 		{
4070 			if (ml[it].Color != CommonStrings::None)
4071 			{
4072 				SetColor(ml[it].Color, ml[it].Shade, &h, &s, &v, &k);
4073 				PS_setcmykcolor_stroke(h, s, v, k);
4074 				PS_setlinewidth(ml[it].Width);
4075 				PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
4076 				PS_setdash(Qt::SolidLine, 0, dum);
4077 				SetClipPath(arrow);
4078 				PS_closepath();
4079 				putColor(ml[it].Color, ml[it].Shade, false);
4080 			}
4081 		}
4082 	}
4083 }
4084 
SetColor(const QString & color,double shade,double * h,double * s,double * v,double * k)4085 void PSLib::SetColor(const QString& color, double shade, double *h, double *s, double *v, double *k)
4086 {
4087 	if (color == CommonStrings::None)
4088 	{
4089 		*h = 0;
4090 		*s = 0;
4091 		*v = 0;
4092 		*k = 0;
4093 		return;
4094 	}
4095 	ScColor& col = m_Doc->PageColors[color];
4096 	SetColor(col, shade, h, s, v, k);
4097 }
4098 
SetColor(const ScColor & color,double shade,double * c,double * m,double * y,double * k)4099 void PSLib::SetColor(const ScColor& color, double shade, double *c, double *m, double *y, double *k)
4100 {
4101 	double c1 = *c, m1 = *m, y1 = *y, k1 = *k;
4102 	ScColor tmp(color);
4103 	if (color.getColorModel() != colorModelCMYK)
4104 		tmp = ScColorEngine::convertToModel(color, m_Doc, colorModelCMYK);
4105 	if ((Options.doGCR) && (!color.isRegistrationColor()))
4106 		ScColorEngine::applyGCR(tmp, m_Doc);
4107 	tmp.getCMYK(&c1, &m1, &y1, &k1);
4108 	if ((m_Doc->HasCMS) && (ScCore->haveCMS()) && (solidTransform))
4109 	{
4110 		c1 = c1 * shade / 100.0;
4111 		m1 = m1 * shade / 100.0;
4112 		y1 = y1 * shade / 100.0;
4113 		k1 = k1 * shade / 100.0;
4114 		unsigned short inC[4];
4115 		unsigned short outC[4];
4116 		inC[0] = c1 * 65535.0;
4117 		inC[1] = m1 * 65535.0;
4118 		inC[2] = y1 * 65535.0;
4119 		inC[3] = k1 * 65535.0;
4120 		solidTransform.apply(inC, outC, 1);
4121 		*c = outC[0] / 65535.0;
4122 		*m = outC[1] / 65535.0;
4123 		*y = outC[2] / 65535.0;
4124 		*k = outC[3] / 65535.0;
4125 	}
4126 	else
4127 	{
4128 		*c = c1 * shade / 100.0;
4129 		*m = m1 * shade / 100.0;
4130 		*y = y1 * shade / 100.0;
4131 		*k = k1 * shade / 100.0;
4132 	}
4133 }
4134 
4135 /**
4136  * @brief PSLib::setTextSt
4137  * @param ite   the text item to set
4138  * @param argh  current page number
4139  * @param pg    current page
4140  * @param master true if setting master page item
4141  */
setTextSt(PageItem * ite,uint argh,ScPage * pg,bool master)4142 void PSLib::setTextSt(PageItem* ite, uint argh, ScPage* pg, bool master)
4143 {
4144 	int savedOwnPage = ite->OwnPage;
4145 	ite->OwnPage = argh;
4146 	ite->layout();
4147 	ite->OwnPage = savedOwnPage;
4148 
4149 	PSPainter p(m_Doc, argh, pg, master, this);
4150 	ite->textLayout.renderBackground(&p);
4151 	ite->textLayout.render(&p);
4152 }
4153 
putColor(const QString & colorName,double shade,bool fill)4154 void PSLib::putColor(const QString& colorName, double shade, bool fill)
4155 {
4156 	ScColor& color(colorsToUse[colorName]);
4157 	if (fill)
4158 	{
4159 		if (((color.isSpotColor()) || (color.isRegistrationColor())) && (Options.useSpotColors))
4160 		{
4161 			if (!DoSep)
4162 				PS_fillspot(colorName, shade);
4163 			else
4164 			{
4165 				if ((colorName == currentSpot) || (color.isRegistrationColor()))
4166 				{
4167 					if (fillRule)
4168 						PutStream("0 0 0 " + ToStr(shade / 100.0) + " cmyk eofill\n");
4169 					else
4170 						PutStream("0 0 0 " + ToStr(shade / 100.0) + " cmyk fill\n");
4171 				}
4172 				else
4173 				{
4174 					if (fillRule)
4175 						PutStream("0 0 0 0 cmyk eofill\n");
4176 					else
4177 						PutStream("0 0 0 0 cmyk fill\n");
4178 				}
4179 			}
4180 		}
4181 		else
4182 		{
4183 			if (!DoSep || (Plate == 0) || (Plate == 1) || (Plate == 2) || (Plate == 3))
4184 				PS_fill();
4185 			else if (fillRule)
4186 				PutStream("0 0 0 0 cmyk eofill\n");
4187 			else
4188 				PutStream("0 0 0 0 cmyk fill\n");
4189 		}
4190 	}
4191 	else
4192 	{
4193 		if (((color.isSpotColor()) || (color.isRegistrationColor())) && (Options.useSpotColors))
4194 		{
4195 			if (!DoSep)
4196 				PS_strokespot(colorName, shade);
4197 			else
4198 			{
4199 				if ((colorName == currentSpot) || (color.isRegistrationColor()))
4200 					PutStream("0 0 0 " + ToStr(shade / 100.0) + " cmyk st\n");
4201 			}
4202 		}
4203 		else
4204 		{
4205 			if (!DoSep || (Plate == 0) || (Plate == 1) || (Plate == 2) || (Plate == 3))
4206 				PS_stroke();
4207 			else
4208 				PutStream("0 0 0 0 cmyk st\n");
4209 		}
4210 	}
4211 }
4212 
putColorNoDraw(const QString & colorName,double shade)4213 void PSLib::putColorNoDraw(const QString& colorName, double shade)
4214 {
4215 	ScColor& color(colorsToUse[colorName]);
4216 	if (((color.isSpotColor()) || (color.isRegistrationColor())) && (Options.useSpotColors))
4217 	{
4218 		if (!DoSep)
4219 			PutStream(ToStr(shade / 100.0) + " " + spotMap[colorName] + "\n");
4220 		else if ((colorName == currentSpot) || (color.isRegistrationColor()))
4221 			PutStream("0 0 0 " + ToStr(shade / 100.0) + " cmyk\n");
4222 		else
4223 			PutStream("0 0 0 0 cmyk\n");
4224 	}
4225 	else
4226 	{
4227 		double c=0, m=0, y=0, k=0;
4228 		SetColor(color, shade, &c, &m, &y, &k);
4229 		if (!DoSep || (Plate == 0 || Plate == 1 || Plate == 2 || Plate == 3))
4230 			PutStream(ToStr(c) + " " + ToStr(m) + " " + ToStr(y) + " " + ToStr(k) + " cmyk\n");
4231 		else
4232 			PutStream("0 0 0 0 cmyk\n");
4233 	}
4234 }
4235 
GetBleeds(ScPage * page,double & left,double & right)4236 void PSLib::GetBleeds(ScPage* page, double& left, double& right)
4237 {
4238 	MarginStruct values;
4239 	m_Doc->getBleeds(page, Options.bleeds, values);
4240 	left   = values.left();
4241 	right  = values.right();
4242 }
4243 
GetBleeds(ScPage * page,double & left,double & right,double & bottom,double & top)4244 void PSLib::GetBleeds(ScPage* page, double& left, double& right, double& bottom, double& top)
4245 {
4246 	MarginStruct values;
4247 	m_Doc->getBleeds(page, Options.bleeds, values);
4248 	left   = values.left();
4249 	right  = values.right();
4250 	bottom = values.bottom();
4251 	top    = values.top();
4252 }
4253 
SetClipPath(const FPointArray & points,bool poly)4254 void PSLib::SetClipPath(const FPointArray &points, bool poly)
4255 {
4256 	FPoint np, np1, np2, np3, np4, firstP;
4257 	bool nPath = true;
4258 	bool first = true;
4259 	if (points.size() <= 3)
4260 		return;
4261 
4262 	for (int poi=0; poi < points.size() - 3; poi += 4)
4263 	{
4264 		if (points.isMarker(poi))
4265 		{
4266 			nPath = true;
4267 			continue;
4268 		}
4269 		if (nPath)
4270 		{
4271 			np = points.point(poi);
4272 			if ((!first) && (poly) && (np4 == firstP))
4273 				PS_closepath();
4274 			PS_moveto(np.x(), -np.y());
4275 			nPath = false;
4276 			first = false;
4277 			firstP = np;
4278 			np4 = np;
4279 		}
4280 		np = points.point(poi);
4281 		np1 = points.point(poi + 1);
4282 		np2 = points.point(poi + 3);
4283 		np3 = points.point(poi + 2);
4284 		if ((np == np1) && (np2 == np3))
4285 			PS_lineto(np3.x(), -np3.y());
4286 		else
4287 			PS_curve(np1.x(), -np1.y(), np2.x(), -np2.y(), np3.x(), -np3.y());
4288 		np4 = np3;
4289 	}
4290 }
4291 
SetPathAndClip(const FPointArray & path,bool clipRule)4292 void PSLib::SetPathAndClip(const FPointArray &path, bool clipRule)
4293 {
4294 	if (path.size() > 3)
4295 	{
4296 		SetClipPath(path);
4297 		PS_closepath();
4298 		PS_clip(clipRule);
4299 	}
4300 }
4301 
errorMessage()4302 const QString& PSLib::errorMessage()
4303 {
4304 	return ErrorMessage;
4305 }
4306 
cancelRequested()4307 void PSLib::cancelRequested()
4308 {
4309 	abortExport=true;
4310 }
4311