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