Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

pslib.cpp

Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008                           pslib.cpp  -  description
00009                              -------------------
00010     begin                : Sat May 26 2001
00011     copyright            : (C) 2001 by Franz Schmid
00012     email                : Franz.Schmid@altmuehlnet.de
00013  ***************************************************************************/
00014 
00015 /***************************************************************************
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
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 /* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
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++; // cyan/black
00334         if (channels > 1)
00335         {
00336             bytes[pending++] = *imageData++; // magenta
00337             bytes[pending++] = *imageData++; // yellow
00338             bytes[pending++] = *imageData++; // green
00339         }
00340         if (pending >= 1500)
00341         {
00342             writeSuccess &= flateEncode.writeData((const char* ) bytes, pending);
00343             pending = 0;
00344         }
00345     }
00346     // To close the stream
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  //     if (!Art)
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 //  PutStream("Scribusdict begin\n");
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         // Qt4 QBuffer b(buf);
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 //  PutStream("end\n");
00504 //  PutStream("%%EndSetup\n");
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 // when creating EPS files determine the orientation from the bounding box
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         // Bottom Left
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         // Top Left
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         // Bottom Right
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         // Top Right
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         // Bottom Left
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         // Top Left
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         // Bottom Right
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         // Top Right
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;