00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "pslib.h"
00025
00026 #include <QFileInfo>
00027 #include <QImage>
00028 #include <QColor>
00029 #include <QFontInfo>
00030 #include <QList>
00031 #include <QByteArray>
00032 #include <QList>
00033 #include <cstdlib>
00034 #include <QRegExp>
00035 #include <QBuffer>
00036 #include <QStack>
00037
00038 #include "cmsettings.h"
00039 #include "commonstrings.h"
00040 #include "scconfig.h"
00041 #include "pluginapi.h"
00042 #include "prefsmanager.h"
00043 #include "scribusdoc.h"
00044 #include "scribus.h"
00045 #include "scribuscore.h"
00046 #include "scfonts.h"
00047 #include "selection.h"
00048 #include <cmath>
00049 #include "util.h"
00050 #include "util_formats.h"
00051 #include "util_math.h"
00052 #include "multiprogressdialog.h"
00053 #include "scribusapp.h"
00054 #include "scpattern.h"
00055 #include "sccolorengine.h"
00056 #include "scstreamfilter_ascii85.h"
00057 #include "scstreamfilter_flate.h"
00058
00059 #include "text/nlsconfig.h"
00060
00061 PSLib::PSLib(PrintOptions &options, bool psart, SCFonts &AllFonts, QMap<QString, QMap<uint, FPointArray> > DocFonts, ColorList DocColors, bool pdf, bool spot)
00062 {
00063 Options = options;
00064 optimization = OptimizeCompat;
00065 usingGUI=ScCore->usingGUI();
00066 abortExport=false;
00067 QString tmp, tmp2, tmp3, tmp4, CHset;
00068 QStringList wt;
00069 Seiten = 0;
00070 User = "";
00071 Creator = "Scribus" + QString(VERSION);
00072 Titel = "";
00073 FillColor = "0.0 0.0 0.0 0.0";
00074 StrokeColor = "0.0 0.0 0.0 0.0";
00075 Header = psart ? "%!PS-Adobe-3.0\n" : "%!PS-Adobe-3.0 EPSF-3.0\n";
00076 BBox = "";
00077 BBoxH = "";
00078 Art = psart;
00079 isPDF = pdf;
00080 UsedFonts.clear();
00081 Fonts = "";
00082 FontDesc = "";
00083 GraySc = false;
00084 DoSep = false;
00085 abortExport = false;
00086 useSpotColors = spot;
00087 GrayCalc = "/setcmykcolor {exch 0.11 mul add exch 0.59 mul add exch 0.3 mul add\n";
00088 GrayCalc += " dup 1 gt {pop 1} if 1 exch sub oldsetgray} bind def\n";
00089 GrayCalc += "/setrgbcolor {0.11 mul exch 0.59 mul add exch 0.3 mul add\n";
00090 GrayCalc += " oldsetgray} bind def\n";
00091 Farben = "";
00092 FNamen = "";
00093 CMYKColor cmykValues;
00094 ColorList::Iterator itf;
00095 int c, m, y, k;
00096 bool erst = true;
00097 colorsToUse = DocColors;
00098 spotMap.clear();
00099 colorDesc = "";
00100 for (itf = DocColors.begin(); itf != DocColors.end(); ++itf)
00101 {
00102 if (((DocColors[itf.key()].isSpotColor()) || (DocColors[itf.key()].isRegistrationColor())) && (useSpotColors))
00103 {
00104 ScColorEngine::getCMYKValues(DocColors[itf.key()], DocColors.document(), cmykValues);
00105 cmykValues.getValues(c, m, y, k);
00106 colorDesc += "/Spot"+PSEncode(itf.key())+" { [ /Separation (";
00107 if (DocColors[itf.key()].isRegistrationColor())
00108 colorDesc += "All";
00109 else
00110 colorDesc += itf.key();
00111 colorDesc += ")\n";
00112 colorDesc += "/DeviceCMYK\n{\ndup "+ToStr(static_cast<double>(c) / 255)+"\nmul exch dup ";
00113 colorDesc += ToStr(static_cast<double>(m) / 255)+"\nmul exch dup ";
00114 colorDesc += ToStr(static_cast<double>(y) / 255)+"\nmul exch ";
00115 colorDesc += ToStr(static_cast<double>(k) / 255)+" mul }] setcolorspace setcolor} bind def\n";
00116 spotMap.insert(itf.key(), "Spot"+PSEncode(itf.key()));
00117 }
00118 if ((itf.key() != "Cyan") && (itf.key() != "Magenta") && (itf.key() != "Yellow") && (itf.key() != "Black") && DocColors[itf.key()].isSpotColor())
00119 {
00120 ScColorEngine::getCMYKValues(DocColors[itf.key()], DocColors.document(), cmykValues);
00121 cmykValues.getValues(c, m, y, k);
00122 if (!erst)
00123 {
00124 Farben += "%%+ ";
00125 FNamen += "%%+ ";
00126 }
00127 Farben += ToStr(static_cast<double>(c) / 255) + " " + ToStr(static_cast<double>(m) / 255) + " ";
00128 Farben += ToStr(static_cast<double>(y) / 255) + " " + ToStr(static_cast<double>(k) / 255) + " (" + itf.key() + ")\n";
00129 FNamen += "(" + itf.key() + ")\n";
00130 erst = false;
00131 }
00132 }
00133 QMap<QString, QMap<uint, FPointArray> >::Iterator it;
00134 int a = 0;
00135 for (it = DocFonts.begin(); it != DocFonts.end(); ++it)
00136 {
00137
00138 ScFace::FontType type = AllFonts[it.key()].type();
00139
00140 if ((type == ScFace::TTF) || (AllFonts[it.key()].isOTF()) || (AllFonts[it.key()].subset()))
00141 {
00142 QMap<uint, FPointArray>& RealGlyphs(it.value());
00143 FontDesc += "/"+AllFonts[it.key()].psName().simplified().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+
00144 " "+IToStr(RealGlyphs.count()+1)+" dict def\n";
00145 FontDesc += AllFonts[it.key()].psName().simplified().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+" begin\n";
00146 QMap<uint,FPointArray>::Iterator ig;
00147 for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
00148 {
00149 FontDesc += "/G"+IToStr(ig.key())+" { newpath\n";
00150 FPoint np, np1, np2;
00151 bool nPath = true;
00152 if (ig.value().size() > 3)
00153 {
00154 for (uint poi = 0; poi < ig.value().size()-3; poi += 4)
00155 {
00156 if (ig.value().point(poi).x() > 900000)
00157 {
00158 FontDesc += "cl\n";
00159 nPath = true;
00160 continue;
00161 }
00162 if (nPath)
00163 {
00164 np = ig.value().point(poi);
00165 FontDesc += ToStr(np.x()) + " " + ToStr(-np.y()) + " m\n";
00166 nPath = false;
00167 }
00168 np = ig.value().point(poi+1);
00169 np1 = ig.value().point(poi+3);
00170 np2 = ig.value().point(poi+2);
00171 FontDesc += ToStr(np.x()) + " " + ToStr(-np.y()) + " " +
00172 ToStr(np1.x()) + " " + ToStr(-np1.y()) + " " +
00173 ToStr(np2.x()) + " " + ToStr(-np2.y()) + " cu\n";
00174 }
00175 }
00176 FontDesc += "cl\n} bind def\n";
00177 }
00178 FontDesc += "end\n";
00179 }
00180 else
00181 {
00182 UsedFonts.insert(it.key(), "/Fo"+IToStr(a));
00183 Fonts += "/Fo"+IToStr(a)+" /"+AllFonts[it.key()].psName().simplified().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+" findfont definefont pop\n";
00184 if (AllFonts[it.key()].embedPs())
00185 {
00186 QString tmp;
00187 if(AllFonts[it.key()].EmbedFont(tmp))
00188 {
00189 FontDesc += "%%BeginFont: " + AllFonts[it.key()].psName().simplified().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ) + "\n";
00190 FontDesc += tmp + "\n%%EndFont\n";
00191 }
00192 }
00193 GListe gl;
00194 AllFonts[it.key()].glyphNames(gl);
00195 GlyphsOfFont.insert(it.key(), gl);
00196 a++;
00197 }
00198 }
00199 Prolog = "%%BeginProlog\n";
00200 Prolog += "/Scribusdict 100 dict def\n";
00201 Prolog += "Scribusdict begin\n";
00202 Prolog += "/sp {showpage} bind def\n";
00203 Prolog += "/oldsetgray /setgray load def\n";
00204 Prolog += "/cmyk {setcmykcolor} def\n";
00205 Prolog += "/m {moveto} bind def\n";
00206 Prolog += "/l {lineto} bind def\n";
00207 Prolog += "/li {lineto} bind def\n";
00208 Prolog += "/cu {curveto} bind def\n";
00209 Prolog += "/cl {closepath} bind def\n";
00210 Prolog += "/gs {gsave} bind def\n";
00211 Prolog += "/gr {grestore} bind def\n";
00212 Prolog += "/tr {translate} bind def\n";
00213 Prolog += "/ro {rotate} bind def\n";
00214 Prolog += "/sh {show} bind def\n";
00215 Prolog += "/shg {setcmykcolor moveto glyphshow} def\n";
00216 Prolog += "/shgsp {moveto glyphshow} def\n";
00217 Prolog += "/sc {scale} bind def\n";
00218 Prolog += "/se {selectfont} bind def\n";
00219 Prolog += "/sf {setfont} bind def\n";
00220 Prolog += "/sw {setlinewidth} bind def\n";
00221 Prolog += "/f {findfont} bind def\n";
00222 Prolog += "/fi {fill} bind def\n";
00223 Prolog += "/st {stroke} bind def\n";
00224 Prolog += "/shgf {gs dup scale begin cvx exec fill end gr} bind def\n";
00225 Prolog += "/shgs {gs dup 1 exch div currentlinewidth mul sw dup scale\n";
00226 Prolog += " begin cvx exec st end gr} bind def\n";
00227 Prolog += "/bEPS {\n";
00228 Prolog += " /b4_Inc_state save def\n";
00229 Prolog += " /dict_count countdictstack def\n";
00230 Prolog += " /op_count count 1 sub def\n";
00231 Prolog += " userdict begin\n";
00232 Prolog += " /showpage { } def\n";
00233 Prolog += " 0 setgray 0 setlinecap\n";
00234 Prolog += " 1 setlinewidth 0 setlinejoin\n";
00235 Prolog += " 10 setmiterlimit [ ] 0 setdash newpath\n";
00236 Prolog += " /languagelevel where\n";
00237 Prolog += " {pop languagelevel\n";
00238 Prolog += " 1 ne\n";
00239 Prolog += " {false setstrokeadjust false setoverprint\n";
00240 Prolog += " } if } if } bind def\n";
00241 Prolog += "/eEPS { count op_count sub {pop} repeat\n";
00242 Prolog += " countdictstack dict_count sub {end} repeat\n";
00243 Prolog += " b4_Inc_state restore } bind def\n";
00244 Prolog += " end\n";
00245 if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
00246 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";
00247 Prolog += "%%EndProlog\n";
00248 }
00249
00250 void PSLib::PutStream(const QString& c)
00251 {
00252 spoolStream.writeRawData(c.toUtf8().data(), c.length());
00253 }
00254
00255 void PSLib::PutStream(const QByteArray& array, bool hexEnc)
00256 {
00257 if(hexEnc)
00258 WriteASCII85Bytes(array);
00259 else
00260 spoolStream.writeRawData(array.data(), array.size());
00261 }
00262
00263 void PSLib::PutStream(const char* array, int length, bool hexEnc)
00264 {
00265 if(hexEnc)
00266 WriteASCII85Bytes((const unsigned char*) array, length);
00267 else
00268 spoolStream.writeRawData(array, length);
00269 }
00270
00271 bool PSLib::PutImageToStream(ScImage& image, int plate)
00272 {
00273 bool writeSucceed = false;
00274 ScASCII85EncodeFilter asciiEncode(&spoolStream);
00275 ScFlateEncodeFilter flateEncode(&asciiEncode);
00276 if (flateEncode.openFilter())
00277 {
00278 writeSucceed = image.writePSImageToFilter(&flateEncode, plate);
00279 writeSucceed &= flateEncode.closeFilter();
00280 }
00281 return writeSucceed;
00282 }
00283
00284 bool PSLib::PutImageToStream(ScImage& image, const QByteArray& mask, int plate)
00285 {
00286 bool writeSucceed = false;
00287 ScASCII85EncodeFilter asciiEncode(&spoolStream);
00288 ScFlateEncodeFilter flateEncode(&asciiEncode);
00289 if (flateEncode.openFilter())
00290 {
00291 writeSucceed = image.writePSImageToFilter(&flateEncode, mask, plate);
00292 writeSucceed &= flateEncode.closeFilter();
00293 }
00294 return writeSucceed;
00295 }
00296
00297 bool PSLib::PutImageDataToStream(const QByteArray& image)
00298 {
00299 bool writeSucceed = false;
00300 ScASCII85EncodeFilter asciiEncode(&spoolStream);
00301 ScFlateEncodeFilter flateEncode(&asciiEncode);
00302 if (flateEncode.openFilter())
00303 {
00304 writeSucceed = flateEncode.writeData(image, image.size());
00305 writeSucceed &= flateEncode.closeFilter();
00306 }
00307 return writeSucceed;
00308 }
00309
00310 bool PSLib::PutInterleavedImageMaskToStream(const QByteArray& image, const QByteArray& mask, bool gray)
00311 {
00312 int pending = 0;
00313 int bIndex = 0;
00314 unsigned char bytes[1505];
00315 const unsigned char* imageData = (const unsigned char*) image.constData();
00316 const unsigned char* maskData = (const unsigned char*) mask.constData();
00317 bool writeSuccess = true;
00318
00319 int channels = gray ? 1 : 4;
00320 int pixels = image.size() / channels;
00321 assert((image.size() % channels) == 0);
00322 assert( mask.size() >= pixels );
00323
00324 ScASCII85EncodeFilter asciiEncode(&spoolStream);
00325 ScFlateEncodeFilter flateEncode(&asciiEncode);
00326 if (!flateEncode.openFilter())
00327 return false;
00328
00329 for (int i = 0; i < pixels; ++i)
00330 {
00331 bIndex = 4 *i;
00332 bytes[pending++] = maskData [i];
00333 bytes[pending++] = *imageData++;
00334 if (channels > 1)
00335 {
00336 bytes[pending++] = *imageData++;
00337 bytes[pending++] = *imageData++;
00338 bytes[pending++] = *imageData++;
00339 }
00340 if (pending >= 1500)
00341 {
00342 writeSuccess &= flateEncode.writeData((const char* ) bytes, pending);
00343 pending = 0;
00344 }
00345 }
00346
00347 if (pending > 0)
00348 writeSuccess &= flateEncode.writeData((const char* ) bytes, pending);
00349 writeSuccess &= flateEncode.closeFilter();
00350 return writeSuccess;
00351 }
00352
00353 void PSLib::WriteASCII85Bytes(const QByteArray& array)
00354 {
00355 WriteASCII85Bytes((const unsigned char*) array.data(), array.size());
00356 }
00357
00358 void PSLib::WriteASCII85Bytes(const unsigned char* array, int length)
00359 {
00360 ScASCII85EncodeFilter filter(&spoolStream);
00361 filter.openFilter();
00362 filter.writeData((const char*) array, length);
00363 filter.closeFilter();
00364 }
00365
00366 QString PSLib::ToStr(double c)
00367 {
00368 QString cc;
00369 return cc.setNum(c);
00370 }
00371
00372 QString PSLib::IToStr(int c)
00373 {
00374 QString cc;
00375 return cc.setNum(c);
00376 }
00377
00378 void PSLib::PS_set_Info(QString art, QString was)
00379 {
00380 if (art == "Author")
00381 User = was;
00382 if (art == "Creator")
00383 Creator = was;
00384 if (art == "Title")
00385 Titel = was;
00386 }
00387
00388 bool PSLib::PS_set_file(QString fn)
00389 {
00390 Spool.setFileName(fn);
00391 if (Spool.exists())
00392 Spool.remove();
00393 bool ret = Spool.open(QIODevice::WriteOnly);
00394 spoolStream.setDevice(&Spool);
00395 return ret;
00396 }
00397
00398 bool PSLib::PS_begin_doc(ScribusDoc *doc, double x, double y, double breite, double hoehe, int numpage, bool doDev, bool sep, bool farb, bool ic, bool gcr, bool over)
00399 {
00400 m_Doc = doc;
00401 PutStream(Header);
00402 PutStream("%%For: " + User + "\n");
00403 PutStream("%%Title: " + Titel + "\n");
00404 PutStream("%%Creator: " + Creator + "\n");
00405 PutStream("%%Pages: " + IToStr(numpage) + "\n");
00406 BBox = "%%BoundingBox: " + IToStr(qRound(x)) + " " + IToStr(qRound(y)) + " " + IToStr(qRound(breite)) + " " + IToStr(qRound(hoehe)) + "\n";
00407 BBoxH = "%%HiResBoundingBox: " + ToStr(x) + " " + ToStr(y) + " " + ToStr(breite) + " " + ToStr(hoehe) + "\n";
00408
00409
00410 PutStream(BBox);
00411 PutStream(BBoxH);
00412
00413 if (!FNamen.isEmpty())
00414 PutStream("%%DocumentCustomColors: "+FNamen);
00415 if (!Farben.isEmpty())
00416 PutStream("%%CMYKCustomColor: "+Farben);
00417 PutStream("%%LanguageLevel: 3\n");
00418 PutStream("%%EndComments\n");
00419 PutStream(Prolog);
00420 PutStream("%%BeginSetup\n");
00421 PutStream("/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse\n");
00422 if (!FontDesc.isEmpty())
00423 PutStream(FontDesc);
00424 if ((!colorDesc.isEmpty()) && (!sep))
00425 PutStream(colorDesc);
00426
00427 PutStream(Fonts);
00428 if (GraySc)
00429 PutStream(GrayCalc);
00430 if (over)
00431 {
00432 PutStream("true setoverprint\n");
00433 PutStream("true setoverprintmode\n");
00434 }
00435 QStringList patterns = m_Doc->getUsedPatterns();
00436 for (int c = 0; c < patterns.count(); ++c)
00437 {
00438 ScPattern pa = m_Doc->docPatterns[patterns[c]];
00439 for (int em = 0; em < pa.items.count(); ++em)
00440 {
00441 PageItem* item = pa.items.at(em);
00442 if ((item->asImageFrame()) && (item->PicAvail) && (!item->Pfile.isEmpty()) && (item->printEnabled()) && (!sep) && (farb))
00443 {
00444 if (!PS_ImageData(item, item->Pfile, item->itemName(), item->IProfile, item->UseEmbedded, ic))
00445 return false;
00446 }
00447 }
00448 PutStream("/Pattern"+patterns[c]+" 8 dict def\n");
00449 PutStream("Pattern"+patterns[c]+" begin\n");
00450 PutStream("/PatternType 1 def\n");
00451 PutStream("/PaintType 1 def\n");
00452 PutStream("/TilingType 1 def\n");
00453 PutStream("/BBox [ 0 0 "+ToStr(pa.width)+" "+ToStr(pa.height)+"] def\n");
00454 PutStream("/XStep "+ToStr(pa.width)+" def\n");
00455 PutStream("/YStep "+ToStr(pa.height)+" def\n");
00456 PutStream("/PaintProc {\n");
00457 QIODevice *spStream = spoolStream.device();
00458 QByteArray buf;
00459
00460 QBuffer b(&buf);
00461 b.open( QIODevice::WriteOnly );
00462 spoolStream.setDevice(&b);
00463 QStack<PageItem*> groupStack;
00464 for (int em = 0; em < pa.items.count(); ++em)
00465 {
00466 PageItem* item = pa.items.at(em);
00467 if (item->isGroupControl)
00468 {
00469 PS_save();
00470 FPointArray cl = item->PoLine.copy();
00471 QMatrix mm;
00472 mm.translate(item->gXpos, item->gYpos - pa.height);
00473 mm.rotate(item->rotation());
00474 cl.map( mm );
00475 SetClipPath(&cl);
00476 PS_closepath();
00477 PS_clip(true);
00478 groupStack.push(item->groupsLastItem);
00479 continue;
00480 }
00481 PutStream("{\n");
00482 PS_save();
00483 PS_translate(item->gXpos, pa.height - item->gYpos);
00484 ProcessItem(m_Doc, m_Doc->Pages->at(0), item, 0, sep, farb, ic, gcr, false, true, true);
00485 PS_restore();
00486 if (groupStack.count() != 0)
00487 {
00488 while (item == groupStack.top())
00489 {
00490 PS_restore();
00491 groupStack.pop();
00492 if (groupStack.count() == 0)
00493 break;
00494 }
00495 }
00496 PutStream("} exec\n");
00497 }
00498 spoolStream.setDevice(spStream);
00499 PutStream(buf);
00500 PutStream("} def\n");
00501 PutStream("end\n");
00502 }
00503
00504
00505 Prolog = "";
00506 FontDesc = "";
00507 return true;
00508 }
00509
00510 QString PSLib::PSEncode(QString in)
00511 {
00512 static QRegExp badchars("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]");
00513 QString tmp = "";
00514 tmp = in.simplified().replace( badchars, "_" );
00515 return tmp;
00516 }
00517
00518 void PSLib::PS_TemplateStart(QString Name)
00519 {
00520 PutStream("/"+PSEncode(Name)+"\n{\n");
00521 }
00522
00523 void PSLib::PS_UseTemplate(QString Name)
00524 {
00525 PutStream(PSEncode(Name)+"\n");
00526 }
00527
00528 void PSLib::PS_TemplateEnd()
00529 {
00530 PutStream("} bind def\n");
00531 }
00532
00533 void PSLib::PS_begin_page(Page* pg, MarginStruct* Ma, bool Clipping)
00534 {
00535 double bleedRight = 0.0;
00536 double bleedLeft = 0.0;
00537 double markOffs = 0.0;
00538 if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
00539 markOffs = 20.0 + Options.markOffset;
00540 if (m_Doc->pageSets[m_Doc->currentPageLayout].Columns == 1)
00541 {
00542 bleedRight = Options.bleeds.Right;
00543 bleedLeft = Options.bleeds.Left;
00544 }
00545 else
00546 {
00547 if (m_Doc->locationOfPage(pg->pageNr()) == LeftPage)
00548 {
00549 bleedRight = Options.bleeds.Right;
00550 bleedLeft = Options.bleeds.Left;
00551 }
00552 else if (m_Doc->locationOfPage(pg->pageNr()) == RightPage)
00553 {
00554 bleedRight = Options.bleeds.Left;
00555 bleedLeft = Options.bleeds.Right;
00556 }
00557 else
00558 {
00559 bleedRight = Options.bleeds.Left;
00560 bleedLeft = Options.bleeds.Left;
00561 }
00562 }
00563 double maxBoxX = pg->width()+bleedLeft+bleedRight+markOffs*2.0;
00564 double maxBoxY = pg->height()+Options.bleeds.Bottom+Options.bleeds.Top+markOffs*2.0;
00565 Seiten++;
00566 PutStream("%%Page: " + IToStr(Seiten) + " " + IToStr(Seiten) + "\n");
00567 PutStream("%%PageOrientation: ");
00568
00569 if (!Art)
00570 {
00571 if ((pg->width() - Ma->Left - Ma->Right) <= (pg->height() - Ma->Bottom - Ma->Top))
00572 PutStream("Portrait\n");
00573 else
00574 PutStream("Landscape\n");
00575 }
00576 else
00577 {
00578 if (pg->PageOri == 0)
00579 PutStream("Portrait\n");
00580 else
00581 PutStream("Landscape\n");
00582 }
00583 PutStream("%%PageBoundingBox: 0 0 "+IToStr(qRound(maxBoxX))+" "+IToStr(qRound(maxBoxY))+"\n");
00584 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");
00585 PutStream("Scribusdict begin\n");
00586 PutStream("save\n");
00587 if (Clipping)
00588 PutStream(PDev);
00589 PutStream("/DeviceCMYK setcolorspace\n");
00590 if ((Art) && (Options.setDevParam))
00591 {
00592 PutStream("<< /PageSize [ "+ToStr(maxBoxX)+" "+ToStr(maxBoxY)+" ]\n");
00593 PutStream(">> setpagedevice\n");
00594 }
00595 PutStream(ToStr(bleedLeft+markOffs)+" "+ToStr(Options.bleeds.Bottom+markOffs)+" tr\n");
00596 ActPage = pg;
00597 if (Clipping)
00598 {
00599 PDev = ToStr(Ma->Left) + " " + ToStr(Ma->Bottom) + " m\n";
00600 PDev += ToStr(pg->width() - Ma->Right) + " " + ToStr(Ma->Bottom) + " li\n";
00601 PDev += ToStr(pg->width() - Ma->Right) + " " + ToStr(pg->height() - Ma->Top) + " li\n";
00602 PDev += ToStr(Ma->Left) + " " + ToStr(pg->height() - Ma->Top) + " li cl clip newpath\n";
00603 }
00604 }
00605
00606 void PSLib::PS_end_page()
00607 {
00608 PutStream("%%PageTrailer\nrestore\n");
00609 double markOffs = 0.0;
00610 if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
00611 markOffs = 20.0 + Options.markOffset;
00612 double bleedRight;
00613 double bleedLeft;
00614 if (m_Doc->pageSets[m_Doc->currentPageLayout].Columns == 1)
00615 {
00616 bleedRight = Options.bleeds.Right;
00617 bleedLeft = Options.bleeds.Left;
00618 }
00619 else
00620 {
00621 if (m_Doc->locationOfPage(ActPage->pageNr()) == LeftPage)
00622 {
00623 bleedRight = Options.bleeds.Right;
00624 bleedLeft = Options.bleeds.Left;
00625 }
00626 else if (m_Doc->locationOfPage(ActPage->pageNr()) == RightPage)
00627 {
00628 bleedRight = Options.bleeds.Left;
00629 bleedLeft = Options.bleeds.Right;
00630 }
00631 else
00632 {
00633 bleedRight = Options.bleeds.Left;
00634 bleedLeft = Options.bleeds.Left;
00635 }
00636 }
00637 double maxBoxX = ActPage->width()+bleedLeft+bleedRight+markOffs*2.0;
00638 double maxBoxY = ActPage->height()+Options.bleeds.Bottom+Options.bleeds.Top+markOffs*2.0;
00639 if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks))
00640 {
00641 PutStream("gs\n");
00642 PS_setlinewidth(0.5);
00643 PutStream("[] 0 setdash\n");
00644 PutStream("0 setlinecap\n");
00645 PutStream("0 setlinejoin\n");
00646 PutStream("1 rb\n");
00647 if (Options.cropMarks)
00648 {
00649
00650 PutStream("0 "+ToStr(markOffs+Options.bleeds.Bottom)+" m\n");
00651 PutStream(ToStr(20.0)+" "+ToStr(markOffs+Options.bleeds.Bottom)+" li\n");
00652 PutStream("st\n");
00653 PutStream(ToStr(markOffs+bleedLeft)+" 0 m\n");
00654 PutStream(ToStr(markOffs+bleedLeft)+" 20 li\n");
00655 PutStream("st\n");
00656
00657 PutStream("0 "+ToStr(maxBoxY-Options.bleeds.Top-markOffs)+" m\n");
00658 PutStream(ToStr(20.0)+" "+ToStr(maxBoxY-Options.bleeds.Top-markOffs)+" li\n");
00659 PutStream("st\n");
00660 PutStream(ToStr(markOffs+bleedLeft)+" "+ToStr(maxBoxY)+" m\n");
00661 PutStream(ToStr(markOffs+bleedLeft)+" "+ToStr(maxBoxY-20.0)+" li\n");
00662 PutStream("st\n");
00663
00664 PutStream(ToStr(maxBoxX)+" "+ToStr(markOffs+Options.bleeds.Bottom)+" m\n");
00665 PutStream(ToStr(maxBoxX-20.0)+" "+ToStr(markOffs+Options.bleeds.Bottom)+" li\n");
00666 PutStream("st\n");
00667 PutStream(ToStr(maxBoxX-bleedRight-markOffs)+" "+ToStr(0.0)+" m\n");
00668 PutStream(ToStr(maxBoxX-bleedRight-markOffs)+" "+ToStr(20.0)+" li\n");
00669 PutStream("st\n");
00670
00671 PutStream(ToStr(maxBoxX)+" "+ToStr(maxBoxY-Options.bleeds.Top-markOffs)+" m\n");
00672 PutStream(ToStr(maxBoxX-20.0)+" "+ToStr(maxBoxY-Options.bleeds.Top-markOffs)+" li\n");
00673 PutStream("st\n");
00674 PutStream(ToStr(maxBoxX-bleedRight-markOffs)+" "+ToStr(maxBoxY)+" m\n");
00675 PutStream(ToStr(maxBoxX-bleedRight-markOffs)+" "+ToStr(maxBoxY-20.0)+" li\n");
00676 PutStream("st\n");
00677 }
00678 if (Options.bleedMarks)
00679 {
00680 PutStream("gs\n");
00681 PutStream("[3 1 1 1] 0 setdash\n");
00682
00683 PutStream("0 "+ToStr(markOffs)+" m\n");
00684 PutStream(ToStr(20.0)+" "+ToStr(markOffs)+" li\n");
00685 PutStream("st\n");
00686 PutStream(ToStr(markOffs)+" 0 m\n");
00687 PutStream(ToStr(markOffs)+" 20 l\n");
00688 PutStream("st\n");
00689
00690 PutStream("0 "+ToStr(maxBoxY-markOffs)+" m\n");
00691 PutStream(ToStr(20.0)+" "+ToStr(maxBoxY-markOffs)+" li\n");
00692 PutStream("st\n");
00693 PutStream(ToStr(markOffs)+" "+ToStr(maxBoxY)+" m\n");
00694 PutStream(ToStr(markOffs)+" "+ToStr(maxBoxY-20.0)+" li\n");
00695 PutStream("st\n");
00696
00697 PutStream(ToStr(maxBoxX)+" "+ToStr(markOffs)+" m\n");
00698 PutStream(ToStr(maxBoxX-20.0)+" "+ToStr(markOffs)+" li\n");
00699 PutStream("st\n");
00700 PutStream(ToStr(maxBoxX-markOffs)+" "+ToStr(0.0)+" m\n");
00701 PutStream(ToStr(maxBoxX-markOffs)+" "+ToStr(20.0)+" li\n");
00702 PutStream("st\n");
00703
00704 PutStream(ToStr(maxBoxX)+" "+ToStr(maxBoxY-markOffs)+" m\n");
00705 PutStream(ToStr(maxBoxX-20.0)+" "+ToStr(maxBoxY-markOffs)+" li\n");
00706 PutStream("st\n");
00707 PutStream(ToStr(maxBoxX-markOffs)+" "+ToStr(maxBoxY)+" m\n");
00708 PutStream(ToStr(maxBoxX-markOffs)+" "+ToStr(maxBoxY-20.0)+" li\n");
00709 PutStream("st\n");
00710 PutStream("gr\n");
00711 }
00712 if (Options.registrationMarks)
00713 {
00714 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";
00715 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";
00716 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";
00717 PutStream("gs\n");
00718 PutStream(ToStr(maxBoxX / 2.0 - 7.0)+" 3 tr\n");
00719 PutStream(regCross);
00720 PutStream("gr\n");
00721 PutStream("gs\n");
00722 PutStream("3 "+ToStr(maxBoxY / 2.0 - 7.0)+" tr\n");
00723 PutStream(regCross);
00724 PutStream("gr\n");
00725 PutStream("gs\n");
00726 PutStream(ToStr(maxBoxX / 2.0 - 7.0)+" "+ToStr(maxBoxY - 17.0)+" tr\n");
00727 PutStream(regCross);
00728 PutStream("gr\n");
00729 PutStream("gs\n");
00730 PutStream(ToStr(maxBoxX - 17.0)+" "+ToStr(maxBoxY / 2.0 - 7.0)+" tr\n");
00731 PutStream(regCross);
00732 PutStream("gr\n");
00733 }
00734 if (Options.colorMarks)
00735 {
00736 double startX = markOffs+bleedLeft+6.0;
00737 double startY = maxBoxY - 18.0;
00738 PutStream("0 0 0 1 cmyk\n");
00739 double col = 1.0;
00740 for (int bl = 0; bl < 11; bl++)
00741 {
00742 PutStream("0 0 0 "+ToStr(col)+" cmyk\n");
00743 PutStream(ToStr(startX+bl*14.0)+" "+ToStr(startY)+" 14 14 rectfill\n");
00744 PutStream("0 0 0 1 cmyk\n");
00745 PutStream(ToStr(startX+bl*14.0)+" "+ToStr(startY)+" 14 14 rectstroke\n");
00746 col -= 0.1;