Back to index

scribus-ng  1.3.4.dfsg+svn20071115
importps.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 #include "importps.h"
00008 #include "importps.moc"
00009 
00010 #include "scconfig.h"
00011 #include "scribus.h"
00012 #include "scribuscore.h"
00013 #include "commonstrings.h"
00014 #include "customfdialog.h"
00015 #include "mpalette.h"
00016 #include "prefsfile.h"
00017 #include "prefscontext.h"
00018 #include "prefsmanager.h"
00019 #include "prefstable.h"
00020 #include "scribusXml.h"
00021 #include <qfile.h>
00022 #include <qtextstream.h>
00023 #include <qcursor.h>
00024 #include <qdragobject.h>
00025 #include <qregexp.h>
00026 #include <qptrstack.h>
00027 #include <qvaluestack.h>
00028 #include <cmath>
00029 #include <cstdlib>
00030 
00031 #include "multiprogressdialog.h"
00032 #include "scpaths.h"
00033 #include "selection.h"
00034 #include "prefsmanager.h"
00035 #include "undomanager.h"
00036 #include "loadsaveplugin.h"
00037 #include "util.h"
00038 
00039 extern SCRIBUS_API ScribusQApp * ScQApp;
00040 
00041 EPSPlug::EPSPlug(ScribusDoc* doc, int flags)
00042 {
00043        tmpSel=new Selection(this, false);
00044        m_Doc=doc;
00045        interactive = (flags & LoadSavePlugin::lfInteractive);
00046 }
00047 
00048 bool EPSPlug::import(QString fName, int flags, bool showProgress)
00049 {
00050        bool success = false;
00051        interactive = (flags & LoadSavePlugin::lfInteractive);
00052        cancel = false;
00053        double x, y, b, h, c, m, k;
00054        bool ret = false;
00055        bool found = false;
00056        CustColors.clear();
00057        QFileInfo fi = QFileInfo(fName);
00058        QString ext = fi.extension(false).lower();
00059        if ( !ScCore->usingGUI() ) {
00060               interactive = false;
00061               showProgress = false;
00062        }
00063        if ( showProgress ) 
00064        {
00065               ScribusMainWindow* mw=(m_Doc==0) ? ScCore->primaryMainWindow() : m_Doc->scMW();
00066               progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw, "psexportprogress");
00067               QStringList barNames, barTexts;
00068               barNames << "GI";
00069               barTexts << tr("Analyzing PostScript:");
00070               QValueList<bool> barsNumeric;
00071               barsNumeric << false;
00072               progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
00073               progressDialog->setOverallTotalSteps(3);
00074               progressDialog->setOverallProgress(0);
00075               progressDialog->setProgress("GI", 0);
00076               progressDialog->show();
00077               connect(progressDialog->buttonCancel, SIGNAL(clicked()), this, SLOT(cancelRequested()));
00078               qApp->processEvents();
00079        }
00080        else {
00081               progressDialog = NULL;
00082        }
00083        
00084 /* Set default Page to size defined in Preferences */
00085        x = 0.0;
00086        y = 0.0;
00087        b = PrefsManager::instance()->appPrefs.PageWidth;
00088        h = PrefsManager::instance()->appPrefs.PageHeight;
00089        if ((ext == "eps") || (ext == "epsi") || (ext == "ps"))
00090        {
00091               QString tmp, BBox, tmp2, FarNam;
00092               ScColor cc;
00093               QFile f(fName);
00094               if (f.open(IO_ReadOnly))
00095               {
00096 /* Try to find Bounding Box */
00097                      QTextStream ts(&f);
00098                      while (!ts.atEnd())
00099                      {
00100                             tmp = ts.readLine();
00101                             if (tmp.startsWith("%%BoundingBox:"))
00102                             {
00103                                    found = true;
00104                                    BBox = tmp.remove("%%BoundingBox:");
00105                             }
00106                             if (!found)
00107                             {
00108                                    if (tmp.startsWith("%%BoundingBox"))
00109                                    {
00110                                           found = true;
00111                                           BBox = tmp.remove("%%BoundingBox");
00112                                    }
00113                             }
00114 /* Read CustomColors if available */
00115                             if (tmp.startsWith("%%CMYKCustomColor"))
00116                             {
00117                                    tmp = tmp.remove(0,18);
00118                                    QTextStream ts2(&tmp, IO_ReadOnly);
00119                                    ts2 >> c >> m >> y >> k;
00120                                    FarNam = ts2.read();
00121                                    FarNam = FarNam.stripWhiteSpace();
00122                                    FarNam = FarNam.remove(0,1);
00123                                    FarNam = FarNam.remove(FarNam.length()-1,1);
00124 //                                 QRegExp badchars("[\\s\\/\\{\\[\\]\\}\<\>\\(\\)\\%]");
00125 //                                 FarNam = FarNam.simplifyWhiteSpace().replace( badchars, "_" );
00126                                    cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * y), qRound(255 * k));
00127                                    cc.setSpotColor(true);
00128                                    CustColors.insert(FarNam, cc);
00129                                    importedColors.append(FarNam);
00130                                    while (!ts.atEnd())
00131                                    {
00132                                           uint oldPos = ts.device()->at();
00133                                           tmp = ts.readLine();
00134                                           if (!tmp.startsWith("%%+"))
00135                                           {
00136                                                  ts.device()->at(oldPos);
00137                                                  break;
00138                                           }
00139                                           tmp = tmp.remove(0,3);
00140                                           QTextStream ts2(&tmp, IO_ReadOnly);
00141                                           ts2 >> c >> m >> y >> k;
00142                                           FarNam = ts2.read();
00143                                           FarNam = FarNam.stripWhiteSpace();
00144                                           FarNam = FarNam.remove(0,1);
00145                                           FarNam = FarNam.remove(FarNam.length()-1,1);
00146 //                                        QRegExp badchars("[\\s\\/\\{\\[\\]\\}\<\>\\(\\)\\%]");
00147 //                                        FarNam = FarNam.simplifyWhiteSpace().replace( badchars, "_" );
00148                                           cc = ScColor(qRound(255 * c), qRound(255 * m), qRound(255 * y), qRound(255 * k));
00149                                           cc.setSpotColor(true);
00150                                           CustColors.insert(FarNam, cc);
00151                                           importedColors.append(FarNam);
00152                                    }
00153                             }
00154                             if (tmp.startsWith("%%EndComments"))
00155                                    break;
00156                      }
00157                      f.close();
00158                      if (found)
00159                      {
00160                             QStringList bb = QStringList::split(" ", BBox);
00161                             if (bb.count() == 4)
00162                             {
00163                                    QTextStream ts2(&BBox, IO_ReadOnly);
00164                                    ts2 >> x >> y >> b >> h;
00165                             }
00166                      }
00167               }
00168        }
00169        baseX = 0;
00170        baseY = 0;
00171        if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
00172        {
00173               m_Doc->setPage(b-x, h-y, 0, 0, 0, 0, 0, 0, false, false);
00174               m_Doc->addPage(0);
00175               m_Doc->view()->addPage(0, true);
00176               baseX = 0;
00177               baseY = 0;
00178        }
00179        else
00180        {
00181               if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
00182               {
00183                      m_Doc=ScCore->primaryMainWindow()->doFileNew(b-x, h-y, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
00184                      ScCore->primaryMainWindow()->HaveNewDoc();
00185                      ret = true;
00186                      baseX = 0;
00187                      baseY = 0;
00188               }
00189        }
00190        if ((!ret) && (interactive))
00191        {
00192               baseX = m_Doc->currentPage()->xOffset();
00193               baseY = m_Doc->currentPage()->yOffset();
00194        }
00195        if ((ret) || (!interactive))
00196        {
00197               if (b-x > h-y)
00198                      m_Doc->PageOri = 1;
00199               else
00200                      m_Doc->PageOri = 0;
00201               m_Doc->m_pageSize = "Custom";
00202        }
00203        ColorList::Iterator it;
00204        for (it = CustColors.begin(); it != CustColors.end(); ++it)
00205        {
00206               if (!m_Doc->PageColors.contains(it.key()))
00207                      m_Doc->PageColors.insert(it.key(), it.data());
00208        }
00209        Elements.clear();
00210        FPoint minSize = m_Doc->minCanvasCoordinate;
00211        FPoint maxSize = m_Doc->maxCanvasCoordinate;
00212        m_Doc->setLoading(true);
00213        m_Doc->DoDrawing = false;
00214        m_Doc->view()->updatesOn(false);
00215        m_Doc->scMW()->ScriptRunning = true;
00216        qApp->setOverrideCursor(QCursor(waitCursor), true);
00217        QString CurDirP = QDir::currentDirPath();
00218        QDir::setCurrent(fi.dirPath());
00219        if (convert(fName, x, y, b, h))
00220        {
00221 //            m_Doc->m_Selection->clear();
00222               tmpSel->clear();
00223               QDir::setCurrent(CurDirP);
00224 //            if ((Elements.count() > 1) && (interactive))
00225               if (Elements.count() > 1)
00226               {
00227                      bool isGroup = true;
00228                      int firstElem = -1;
00229                      if (Elements.at(0)->Groups.count() != 0)
00230                             firstElem = Elements.at(0)->Groups.top();
00231                      for (uint bx = 0; bx < Elements.count(); ++bx)
00232                      {
00233                             PageItem* bxi = Elements.at(bx);
00234                             if (bxi->Groups.count() != 0)
00235                             {
00236                                    if (bxi->Groups.top() != firstElem)
00237                                           isGroup = false;
00238                             }
00239                             else
00240                                    isGroup = false;
00241                      }
00242                      if (!isGroup)
00243                      {
00244                             double minx = 99999.9;
00245                             double miny = 99999.9;
00246                             double maxx = -99999.9;
00247                             double maxy = -99999.9;
00248                             uint lowestItem = 999999;
00249                             uint highestItem = 0;
00250                             for (uint a = 0; a < Elements.count(); ++a)
00251                             {
00252                                    Elements.at(a)->Groups.push(m_Doc->GroupCounter);
00253                                    PageItem* currItem = Elements.at(a);
00254                                    lowestItem = QMIN(lowestItem, currItem->ItemNr);
00255                                    highestItem = QMAX(highestItem, currItem->ItemNr);
00256                                    double lw = currItem->lineWidth() / 2.0;
00257                                    if (currItem->rotation() != 0)
00258                                    {
00259                                           FPointArray pb;
00260                                           pb.resize(0);
00261                                           pb.addPoint(FPoint(currItem->xPos()-lw, currItem->yPos()-lw));
00262                                           pb.addPoint(FPoint(currItem->width()+lw*2.0, -lw, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00263                                           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));
00264                                           pb.addPoint(FPoint(-lw, currItem->height()+lw*2.0, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00265                                           for (uint pc = 0; pc < 4; ++pc)
00266                                           {
00267                                                  minx = QMIN(minx, pb.point(pc).x());
00268                                                  miny = QMIN(miny, pb.point(pc).y());
00269                                                  maxx = QMAX(maxx, pb.point(pc).x());
00270                                                  maxy = QMAX(maxy, pb.point(pc).y());
00271                                           }
00272                                    }
00273                                    else
00274                                    {
00275                                           minx = QMIN(minx, currItem->xPos()-lw);
00276                                           miny = QMIN(miny, currItem->yPos()-lw);
00277                                           maxx = QMAX(maxx, currItem->xPos()-lw + currItem->width()+lw*2.0);
00278                                           maxy = QMAX(maxy, currItem->yPos()-lw + currItem->height()+lw*2.0);
00279                                    }
00280                             }
00281                             double gx = minx;
00282                             double gy = miny;
00283                             double gw = maxx - minx;
00284                             double gh = maxy - miny;
00285                             PageItem *high = m_Doc->Items->at(highestItem);
00286                             int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->toolSettings.dBrush, m_Doc->toolSettings.dPen, true);
00287                             PageItem *neu = m_Doc->Items->take(z);
00288                             m_Doc->Items->insert(lowestItem, neu);
00289                             neu->Groups.push(m_Doc->GroupCounter);
00290                             neu->setItemName( tr("Group%1").arg(m_Doc->GroupCounter));
00291                             neu->isGroupControl = true;
00292                             neu->AutoName = false;
00293                             neu->groupsLastItem = high;
00294                             neu->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00295                             for (uint a = 0; a < m_Doc->Items->count(); ++a)
00296                             {
00297                                    m_Doc->Items->at(a)->ItemNr = a;
00298                             }
00299                             Elements.prepend(neu);
00300                             m_Doc->GroupCounter++;
00301                      }
00302               }
00303               m_Doc->DoDrawing = true;
00304               m_Doc->scMW()->ScriptRunning = false;
00305               m_Doc->setLoading(false);
00306               qApp->setOverrideCursor(QCursor(arrowCursor), true);
00307               if ((Elements.count() > 0) && (!ret) && (interactive))
00308               {
00309                      if (flags & LoadSavePlugin::lfScripted)
00310                      {
00311                             bool loadF = m_Doc->isLoading();
00312                             m_Doc->setLoading(false);
00313                             m_Doc->changed();
00314                             m_Doc->setLoading(loadF);
00315                             for (uint dre=0; dre<Elements.count(); ++dre)
00316                             {
00317                                    m_Doc->m_Selection->addItem(Elements.at(dre), true);
00318                             }
00319                             m_Doc->m_Selection->setGroupRect();
00320                             m_Doc->view()->updatesOn(true);
00321                      }
00322                      else
00323                      {
00324                             m_Doc->DragP = true;
00325                             m_Doc->DraggedElem = 0;
00326                             m_Doc->DragElements.clear();
00327                             for (uint dre=0; dre<Elements.count(); ++dre)
00328                             {
00329                                    m_Doc->DragElements.append(Elements.at(dre)->ItemNr);
00330                                    tmpSel->addItem(Elements.at(dre), true);
00331                             }
00332                             tmpSel->setGroupRect();
00333                             ScriXmlDoc *ss = new ScriXmlDoc();
00334                             QDragObject *dr = new QTextDrag(ss->WriteElem(m_Doc, m_Doc->view(), tmpSel),m_Doc->view()->viewport());
00335 #ifndef QT_MAC
00336 // see #2196
00337                             m_Doc->itemSelection_DeleteItem(tmpSel);
00338 #else
00339                             qDebug("psimport: leaving items on page");
00340 #endif
00341                             m_Doc->view()->resizeContents(qRound((maxSize.x() - minSize.x()) * m_Doc->view()->scale()), qRound((maxSize.y() - minSize.y()) * m_Doc->view()->scale()));
00342                             m_Doc->view()->scrollBy(qRound((m_Doc->minCanvasCoordinate.x() - minSize.x()) * m_Doc->view()->scale()), qRound((m_Doc->minCanvasCoordinate.y() - minSize.y()) * m_Doc->view()->scale()));
00343                             m_Doc->minCanvasCoordinate = minSize;
00344                             m_Doc->maxCanvasCoordinate = maxSize;
00345                             m_Doc->view()->updatesOn(true);
00346                             m_Doc->view()->updateContents();
00347                             dr->setPixmap(loadIcon("DragPix.xpm"));
00348 #if 0
00349                      qDebug("psimport: data");
00350                      QString data(dr->encodedData("text/plain"));
00351                      for (uint i=0; i <= data.length() / 4000; i++) {
00352                             qDebug(data.mid(i*4000, 4000));
00353                      }
00354                      qDebug("psimport: enddata");
00355                      qDebug(QString("psimport: drag type %1").arg(dr->format()));
00356 #endif
00357                             dr->drag();
00358                             /*if (!dr->drag())
00359                             {
00360                                    if (importedColors.count() != 0)
00361                                    {
00362                                           for (uint cd = 0; cd < importedColors.count(); cd++)
00363                                           {
00364                                                  m_Doc->PageColors.remove(importedColors[cd]);
00365                                           }
00366                                    }
00367                             }*/
00368                             delete ss;
00369                             m_Doc->DragP = false;
00370                             m_Doc->DraggedElem = 0;
00371                             m_Doc->DragElements.clear();
00372                      }
00373               }
00374               else
00375               {
00376                      m_Doc->changed();
00377                      m_Doc->reformPages();
00378                      m_Doc->view()->updatesOn(true);
00379               }
00380               success = true;
00381        }
00382        else
00383        {
00384               QDir::setCurrent(CurDirP);
00385               m_Doc->DoDrawing = true;
00386               m_Doc->scMW()->ScriptRunning = false;
00387               m_Doc->view()->updatesOn(true);
00388               qApp->setOverrideCursor(QCursor(arrowCursor), true);
00389        }
00390        if (interactive)
00391               m_Doc->setLoading(false);
00392        //CB If we have a gui we must refresh it if we have used the progressbar
00393        if ((showProgress) && (!interactive))
00394               m_Doc->view()->DrawNew();
00395        return success;
00396 }
00397 
00398 EPSPlug::~EPSPlug()
00399 {
00400        delete tmpSel;
00401 }
00402        
00403 
00404 bool EPSPlug::convert(QString fn, double x, double y, double b, double h)
00405 {
00406        QStringList args;
00407        QString cmd, cmd1, cmd2, cmd3, tmp, tmp2, tmp3, tmp4;
00408        // import.prolog do not cope with filenames containing blank spaces
00409        // so take care that output filename does not (win32 compatibility)
00410        QString tmpFile = getShortPathName(ScPaths::getTempFileDir())+ "/ps.out";
00411        QString errFile = getShortPathName(ScPaths::getTempFileDir())+ "/ps.err";
00412        QString pfad = ScPaths::instance().libDir();
00413 #ifdef HAVE_CAIRO
00414        QString pfad2 = QDir::convertSeparators(pfad + "import.prolog");
00415 #else
00416        QString pfad2 = QDir::convertSeparators(pfad + "import_la.prolog");
00417 #endif
00418        QFileInfo fi = QFileInfo(fn);
00419        QString ext = fi.extension(false).lower();
00420        
00421        if (progressDialog) {
00422               progressDialog->setOverallProgress(1);
00423               qApp->processEvents();
00424        }
00425        args.append( getShortPathName(PrefsManager::instance()->ghostscriptExecutable()) );
00426        args.append( "-q" );
00427        args.append( "-dNOPAUSE" );
00428        args.append( "-sDEVICE=nullpage" );
00429        args.append( "-dBATCH" );
00430        args.append( "-dDELAYBIND" );
00431        // Add any extra font paths being used by Scribus to gs's font search
00432        // path We have to use Scribus's prefs context, not a plugin context, to
00433        // get to the required information.
00434        PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
00435        PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
00436        const char sep = ScPaths::envPathSeparator;
00437        if (extraFonts->getRowCount() >= 1)
00438               cmd = QString("-sFONTPATH=%1").arg(extraFonts->get(0,0));
00439        for (int i = 1; i < extraFonts->getRowCount(); ++i)
00440               cmd += QString("%1%2").arg(sep).arg(extraFonts->get(i,0));
00441        if( !cmd.isEmpty() )
00442               args.append( cmd );
00443        // then finish building the command and call gs
00444 #ifdef HAVE_CAIRO
00445        args.append( QString("-g%1x%2").arg(tmp2.setNum(qRound((b-x)))).arg(tmp3.setNum(qRound((h-y)))) );
00446        args.append( "-r72");
00447 #else
00448        args.append( QString("-g%1x%2").arg(tmp2.setNum(qRound((b-x)*4))).arg(tmp3.setNum(qRound((h-y)*4))) );
00449        args.append( "-r288");
00450 #endif
00451        args.append( "-dTextAlphaBits=4" );
00452        args.append( "-dGraphicsAlphaBits=4" );
00453        args.append( "-c" );
00454        args.append( tmp.setNum(-x) );
00455        args.append( tmp.setNum(-y) );
00456        args.append( "translate" );
00457        args.append( QString("-sTraceFile=%1").arg(QDir::convertSeparators(tmpFile)) );
00458        QString exportPath = m_Doc->DocName + "-" + fi.baseName();
00459        QFileInfo exportFi(exportPath);
00460        if ( !exportFi.isWritable() ) {
00461               PrefsContext* docContext = PrefsManager::instance()->prefsFile->getContext("docdirs", false);
00462               QString docDir = ".";
00463               QString prefsDocDir=PrefsManager::instance()->documentDir();
00464               if (!prefsDocDir.isEmpty())
00465                      docDir = docContext->get("docsopen", prefsDocDir);
00466               else
00467                      docDir = docContext->get("docsopen", ".");              
00468               exportFi.setFile(docDir + "/" + exportFi.baseName());
00469        }
00470        //qDebug(QString("using export path %1").arg(exportFi.absFilePath()));
00471        args.append( QString("-sExportFiles=%1").arg(QDir::convertSeparators(exportFi.absFilePath())) );
00472        args.append( pfad2 );
00473        args.append( QDir::convertSeparators(fn) );
00474        args.append( "-c" );
00475        args.append( "flush" );
00476        args.append( "cfile" );
00477        args.append( "closefile" );
00478        args.append( "quit" );
00479        QCString finalCmd = args.join(" ").local8Bit();
00480        int ret = System(args, errFile, errFile);
00481        if (ret != 0)
00482        {
00483               qDebug("PostScript import failed when calling gs as: \n%s\n", finalCmd.data());
00484               qDebug("Ghostscript diagnostics:\n");
00485               QFile diag(errFile);
00486               if (diag.open(IO_ReadOnly) && !diag.atEnd() ) {
00487                      QString line;
00488                      while (diag.readLine(line, 120) > 0) {
00489                             qDebug("\t%s", line.ascii());
00490                      }
00491                      diag.close();
00492               }
00493               else {
00494                      qDebug("-- no output --");
00495               }
00496               if (progressDialog)
00497                      progressDialog->close();
00498               QString mess = tr("Importing File:\n%1\nfailed!").arg(fn);
00499               QMessageBox::critical(0, tr("Fatal Error"), mess, 1, 0, 0);
00500               return false;
00501        }
00502        if(progressDialog) {
00503               progressDialog->setOverallProgress(2);
00504               progressDialog->setLabel("GI", tr("Generating Items"));
00505               qApp->processEvents();
00506        }
00507        if (!cancel) {
00508               parseOutput(tmpFile, ((ext == "eps") || (ext == "epsi")));
00509        }
00510        QFile::remove(tmpFile);
00511        if (progressDialog)
00512               progressDialog->close();
00513        return true;
00514 }
00515 
00516 void EPSPlug::parseOutput(QString fn, bool eps)
00517 {
00518        QString tmp, token, params, lasttoken, lastPath, currPath;
00519        int z, lcap, ljoin, dc, pagecount;
00520        int failedImages = 0;
00521        double dcp;
00522        bool fillRuleEvenOdd = true;
00523        PageItem* ite;
00524        QPtrStack<PageItem> groupStack;
00525        QValueStack<int> gsStack;
00526        QValueStack<uint> elemCount;
00527        QValueStack<uint> gsStackMarks;
00528        QFile f(fn);
00529        lasttoken = "";
00530        pagecount = 1;
00531        if (f.open(IO_ReadOnly))
00532        {
00533               if (progressDialog) {
00534                      progressDialog->setTotalSteps("GI", (int) f.size());
00535                      qApp->processEvents();
00536               }
00537               lastPath = "";
00538               currPath = "";
00539               LineW = 0;
00540               Opacity = 1;
00541               CurrColor = CommonStrings::None;
00542               JoinStyle = MiterJoin;
00543               CapStyle = FlatCap;
00544               DashPattern.clear();
00545               QTextStream ts(&f);
00546               int line_cnt = 0;
00547               while (!ts.atEnd() && !cancel)
00548               {
00549                      tmp = "";
00550                      tmp = ts.readLine();
00551                      if (progressDialog && (++line_cnt % 100 == 0)) {
00552                             progressDialog->setProgress("GI", (int) f.at());
00553                             qApp->processEvents();
00554                      }
00555                      token = tmp.section(' ', 0, 0);
00556                      params = tmp.section(' ', 1, -1, QString::SectionIncludeTrailingSep);
00557                      if (lasttoken == "sp"  && !eps && token != "sp" ) //av: messes up anyway: && (!interactive))
00558                      {
00559                             m_Doc->addPage(pagecount);
00560                             m_Doc->view()->addPage(pagecount, true);
00561                             pagecount++;
00562                      }
00563                      if (token == "n")
00564                      {
00565                             Coords.resize(0);
00566                             FirstM = true;
00567                             WasM = false;
00568                             ClosedPath = false;
00569                      }
00570                      else if (token == "m")
00571                             WasM = true;
00572                      else if (token == "c")
00573                      {
00574                             Curve(&Coords, params);
00575                             currPath += params;
00576                      }
00577                      else if (token == "l")
00578                      {
00579                             LineTo(&Coords, params);
00580                             currPath += params;
00581                      }
00582                      else if (token == "fill-winding")
00583                      {
00584                             fillRuleEvenOdd = false;
00585                      }
00586                      else if (token == "fill-evenodd")
00587                      {
00588                             fillRuleEvenOdd = true;
00589                      }
00590                      else if (token == "f")
00591                      {
00592                             //TODO: pattern -> Imageframe + Clip
00593                             if (Coords.size() != 0)
00594                             {
00595                                    if ((Elements.count() != 0) && (lastPath == currPath))
00596                                    {
00597                                           ite = Elements.at(Elements.count()-1);
00598                                           ite->setFillColor(CurrColor);
00599                                           ite->setFillTransparency(1.0 - Opacity);
00600                                           lastPath = "";
00601                                    }
00602                                    else
00603                                    {
00604                                           if (ClosedPath)
00605                                                  z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColor, CommonStrings::None, true);
00606                                           else
00607                                                  z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CurrColor, CommonStrings::None, true);
00608                                           ite = m_Doc->Items->at(z);
00609                                           ite->PoLine = Coords.copy();  //FIXME: try to avoid copy if FPointArray when properly shared
00610                                           ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
00611                                           ite->ClipEdited = true;
00612                                           ite->FrameType = 3;
00613                                           ite->fillRule = (fillRuleEvenOdd);
00614                                           FPoint wh = getMaxClipF(&ite->PoLine);
00615                                           ite->setWidthHeight(wh.x(),wh.y());
00616                                           ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00617                                           ite->setFillTransparency(1.0 - Opacity);
00618                                           ite->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00619                                           m_Doc->AdjustItemSize(ite);
00620                                           if (groupStack.count() != 0)
00621                                           {
00622                                                  QValueStack<int> groupOld = groupStack.top()->Groups;
00623                                                  for (uint gg = 0; gg < groupOld.count(); gg++)
00624                                                  {
00625                                                         ite->Groups.push(groupOld[gg]);
00626                                                  }
00627                                           }
00628                                           Elements.append(ite);
00629                                           lastPath = currPath;
00630                                    }
00631                                    currPath = "";
00632                             }
00633                      }
00634                      else if (token == "s")
00635                      {
00636                             if (Coords.size() != 0)
00637                             {
00638                                    LineW = QMAX(LineW, 0.1); // Set Linewidth to be a least 0.1 pts, a Stroke without a Linewidth makes no sense
00639                                    if ((Elements.count() != 0) && (lastPath == currPath))
00640                                    {
00641                                           ite = Elements.at(Elements.count()-1);
00642                                           ite->setLineColor(CurrColor);
00643                                           ite->setLineWidth(LineW);
00644                                           ite->PLineEnd = CapStyle;
00645                                           ite->PLineJoin = JoinStyle;
00646                                           ite->setLineTransparency(1.0 - Opacity);
00647                                           ite->DashOffset = DashOffset;
00648                                           ite->DashValues = DashPattern;
00649                                    }
00650                                    else
00651                                    {
00652                                           if (ClosedPath)
00653                                                  z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CommonStrings::None, CurrColor, true);
00654                                           else
00655                                                  z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, LineW, CommonStrings::None, CurrColor, true);
00656                                           ite = m_Doc->Items->at(z);
00657                                           ite->PoLine = Coords.copy(); //FIXME: try to avoid copy when FPointArray is properly shared
00658                                           ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
00659                                           ite->ClipEdited = true;
00660                                           ite->FrameType = 3;
00661                                           ite->PLineEnd = CapStyle;
00662                                           ite->PLineJoin = JoinStyle;
00663                                           ite->DashOffset = DashOffset;
00664                                           ite->DashValues = DashPattern;
00665                                           FPoint wh = getMaxClipF(&ite->PoLine);
00666                                           ite->setWidthHeight(wh.x(), wh.y());
00667                                           ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00668                                           ite->setLineTransparency(1.0 - Opacity);
00669                                           m_Doc->AdjustItemSize(ite);
00670                                           ite->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00671                                           if (groupStack.count() != 0)
00672                                           {
00673                                                  QValueStack<int> groupOld = groupStack.top()->Groups;
00674                                                  for (uint gg = 0; gg < groupOld.count(); gg++)
00675                                                  {
00676                                                         ite->Groups.push(groupOld[gg]);
00677                                                  }
00678                                           }
00679                                           Elements.append(ite);
00680                                    }
00681                                    lastPath = "";
00682                                    currPath = "";
00683                             }
00684                      }
00685                      else if (token == "co")
00686                             CurrColor = parseColor(params, eps);
00687                      else if (token == "corgb")
00688                             CurrColor = parseColor(params, eps, colorModelRGB);
00689                      else if (token == "ci")
00690                      {
00691                             clipCoords = Coords;
00692                             if (Coords.size() != 0)
00693                             {
00694                                    z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX, baseY, 10, 10, 0, CommonStrings::None, CommonStrings::None, true);
00695                                    ite = m_Doc->Items->at(z);
00696                                    ite->PoLine = Coords.copy();  //FIXME: try to avoid copy if FPointArray when properly shared
00697                                    ite->PoLine.translate(m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset());
00698                                    ite->ClipEdited = true;
00699                                    ite->FrameType = 3;
00700 //                                 ite->fillRule = (fillRuleEvenOdd);
00701                                    FPoint wh = getMaxClipF(&ite->PoLine);
00702                                    ite->setWidthHeight(wh.x(),wh.y());
00703                                    ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00704 //                                 ite->setFillTransparency(1.0 - Opacity);
00705                                    m_Doc->AdjustItemSize(ite);
00706                                    ite->Groups.push(m_Doc->GroupCounter);
00707                                    if (groupStack.count() != 0)
00708                                    {
00709                                           QValueStack<int> groupOld = groupStack.top()->Groups;
00710                                           for (uint gg = 0; gg < groupOld.count(); gg++)
00711                                           {
00712                                                  ite->Groups.push(groupOld[gg]);
00713                                           }
00714                                    }
00715                                    ite->isGroupControl = true;
00716                                    ite->setItemName( tr("Group%1").arg(m_Doc->GroupCounter));
00717                                    ite->AutoName = false;
00718                                    ite->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00719                                    Elements.append(ite);
00720                                    elemCount.push(Elements.count());
00721                                    groupStack.push(ite);
00722                                    gsStackMarks.push(gsStack.count());
00723                                    m_Doc->GroupCounter++;
00724                             }
00725                             Coords   = FPointArray(0);
00726                             lastPath = "";
00727                             currPath = "";
00728                      }
00729                      else if (token == "gs")
00730                      {
00731                             gsStack.push(1);
00732                      }
00733                      else if (token == "gr")
00734                      {
00735                             gsStack.pop();
00736                             if (groupStack.count() != 0)
00737                             {
00738                                    if (gsStack.count() < gsStackMarks.top())
00739                                    {
00740                                           PageItem *ite = groupStack.pop();
00741                                           uint count = elemCount.pop();
00742                                           if (count == Elements.count())
00743                                           {
00744                                                  m_Doc->Items->removeLast();
00745                                                  Elements.removeLast();
00746                                           }
00747                                           else
00748                                                  ite->groupsLastItem = Elements.at(Elements.count()-1);
00749                                           gsStackMarks.pop();
00750                                    }
00751                             }
00752                      }
00753                      else if (token == "w")
00754                      {
00755                             QTextStream Lw(&params, IO_ReadOnly);
00756                             Lw >> LineW;
00757 //                          currPath += params;
00758                      }
00759                      else if (token == "ld")
00760                      {
00761                             QTextStream Lw(&params, IO_ReadOnly);
00762                             Lw >> dc;
00763                             Lw >> DashOffset;
00764                             DashPattern.clear();
00765                             if (dc != 0)
00766                             {
00767                                    for (int dcc = 0; dcc < dc; ++dcc)
00768                                    {
00769                                           Lw >> dcp;
00770                                           DashPattern.append(dcp);
00771                                    }
00772                             }
00773 //                          currPath += params;
00774                      }
00775                      else if (token == "lc")
00776                      {
00777                             QTextStream Lw(&params, IO_ReadOnly);
00778                             Lw >> lcap;
00779                             switch (lcap)
00780                             {
00781                                    case 0:
00782                                           CapStyle = Qt::FlatCap;
00783                                           break;
00784                                    case 1:
00785                                           CapStyle = Qt::RoundCap;
00786                                           break;
00787                                    case 2:
00788                                           CapStyle = Qt::SquareCap;
00789                                           break;
00790                                    default:
00791                                           CapStyle = Qt::FlatCap;
00792                                           break;
00793                             }
00794 //                          currPath += params;
00795                      }
00796                      else if (token == "lj")
00797                      {
00798                             QTextStream Lw(&params, IO_ReadOnly);
00799                             Lw >> ljoin;
00800                             switch (ljoin)
00801                             {
00802                                    case 0:
00803                                           JoinStyle = Qt::MiterJoin;
00804                                           break;
00805                                    case 1:
00806                                           JoinStyle = Qt::RoundJoin;
00807                                           break;
00808                                    case 2:
00809                                           JoinStyle = Qt::BevelJoin;
00810                                           break;
00811                                    default:
00812                                           JoinStyle = Qt::MiterJoin;
00813                                           break;
00814                             }
00815 //                          currPath += params;
00816                      }
00817                      else if (token == "cp") {
00818                             ClosedPath = true;
00819                      }
00820                      else if (token == "im") {
00821                             if ( !Image(params) )
00822                                    ++failedImages;
00823                      }
00824                      lasttoken = token;
00825               }
00826               f.close();
00827               if (groupStack.count() != 0)
00828               {
00829                      while (!groupStack.isEmpty())
00830                      {
00831                             PageItem *ite = groupStack.pop();
00832                             uint count = elemCount.pop();
00833                             if (count == Elements.count())
00834                             {
00835                                    m_Doc->Items->removeLast();
00836                                    Elements.removeLast();
00837                             }
00838                             else
00839                                    ite->groupsLastItem = Elements.at(Elements.count()-1);
00840                      }
00841               }
00842        }
00843        if (failedImages > 0)
00844        {
00845               QString mess = tr("Converting of %1 images failed!").arg(failedImages);
00846               QMessageBox::critical(0, tr("Error"), mess, 1, 0, 0);
00847        }
00848 }
00849 
00850 bool EPSPlug::Image(QString vals)
00851 {
00852        double x, y, w, h, angle;
00853        int horpix, verpix;
00854        QString filename, device;
00855        QTextStream Code(&vals, IO_ReadOnly);
00856        Code >> x;
00857        Code >> y;
00858        Code >> w;
00859        Code >> h;
00860        Code >> angle;
00861        Code >> horpix;
00862        Code >> verpix;
00863        Code >> device;
00864        filename = Code.read().stripWhiteSpace();
00865        if (device.startsWith("psd")) {
00866               filename = filename.mid(0, filename.length()-3) + "psd";
00867        }
00868               
00869        qDebug(QString("import %6 image %1: %2x%3 @ (%4,%5) °%5").arg(filename).arg(w).arg(h).arg(x).arg(y).arg(angle).arg(device));
00870        QString rawfile = filename.mid(0, filename.length()-3) + "dat";
00871        QStringList args;
00872        args.append( getShortPathName(PrefsManager::instance()->ghostscriptExecutable()) );
00873        args.append( "-q" );
00874        args.append( "-dNOPAUSE" );
00875        args.append( QString("-sDEVICE=%1").arg(device) );    
00876        args.append( "-dBATCH" );
00877        args.append( QString("-g%1x%2").arg(horpix).arg(verpix) );
00878        args.append( QString("-sOutputFile=%1").arg(QDir::convertSeparators(filename)) );
00879        args.append( QDir::convertSeparators(rawfile) );
00880        args.append( "-c" );
00881        args.append( "showpage" );
00882        args.append( "quit" );
00883        QCString finalCmd = args.join(" ").local8Bit();
00884        int ret = System(args);
00885        if (ret != 0)
00886        {
00887               qDebug("PostScript image conversion failed when calling gs as: \n%s\n", finalCmd.data());
00888               qDebug("Ghostscript diagnostics: %d\n", ret);
00889               QFile diag(filename);
00890               if (diag.open(IO_ReadOnly)) {
00891                      QString line;
00892                      long int len;
00893                      bool gs_error = false;
00894                      do {
00895                             len = diag.readLine(line, 120);
00896                             gs_error |= (line.contains("Error") > 0);
00897                             if (gs_error)
00898                                    qDebug("\t%s", line.ascii());
00899                      }
00900                      while (len > 0);
00901                      diag.close();
00902                      }
00903               else {
00904                      qDebug("-- no output --");
00905               }
00906               qDebug("Failed file was:\n");
00907               QFile dat(rawfile);
00908               if (dat.open(IO_ReadOnly)) {
00909                      QString line;
00910                      long int len;
00911                      do {
00912                             len = dat.readLine(line, 120);
00913                             qDebug("\t%s", line.ascii());
00914                      }
00915                      while ( len > 0 && !line.contains("image") );
00916                      dat.close();
00917               }
00918               else {
00919                      qDebug("-- empty --");
00920               }
00921        }
00922        QFile::remove(rawfile);
00923        int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, m_Doc->currentPage()->xOffset(), m_Doc->currentPage()->yOffset(), w, h, LineW, CommonStrings::None, CurrColor, true);
00924        PageItem * ite = m_Doc->Items->at(z);
00925        ite->setXYPos(m_Doc->currentPage()->xOffset() + x, m_Doc->currentPage()->yOffset() + y);
00926        ite->setWidthHeight(w, h);
00927        ite->clearContents();
00928 /*     FPoint a(x, y);
00929        FPoint b(x+w, y);
00930        FPoint c(x+w, y-h);
00931        FPoint d(x, y-h);
00932        ite->PoLine.resize(0);
00933        ite->PoLine.addQuadPoint(a, a, b, b);
00934        ite->PoLine.addQuadPoint(b, b, c, c);
00935        ite->PoLine.addQuadPoint(c, c, d, d);
00936        ite->PoLine.addQuadPoint(d, d, a, a);
00937        ite->PoLine.translate(m_Doc->currentPage->xOffset() - x, m_Doc->currentPage->yOffset() - y);
00938        ite->ClipEdited = true;
00939        ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00940 */
00941        m_Doc->loadPict(filename, ite, true);
00942        ite->setRotation(angle);
00943        ite->setImageScalingMode(false, true); // fit to frame, keep ratio
00944 //     m_Doc->view()->AdjustItemSize(ite);
00945        Elements.append(ite);
00946        return ret == 0;
00947 }
00948 
00949 
00950 void EPSPlug::LineTo(FPointArray *i, QString vals)
00951 {
00952        if (vals.isEmpty())
00953               return;
00954        double x1, x2, y1, y2;
00955        x1 = vals.section(' ', 0, 0, QString::SectionSkipEmpty).toDouble();
00956        y1 = vals.section(' ', 1, 1, QString::SectionSkipEmpty).toDouble();
00957        x2 = vals.section(' ', 2, 2, QString::SectionSkipEmpty).toDouble();
00958        y2 = vals.section(' ', 3, 3, QString::SectionSkipEmpty).toDouble();
00959        if ((!FirstM) && (WasM))
00960               i->setMarker();
00961        FirstM = false;
00962        WasM = false;
00963        i->addPoint(FPoint(x1, y1));
00964        i->addPoint(FPoint(x1, y1));
00965        i->addPoint(FPoint(x2, y2));
00966        i->addPoint(FPoint(x2, y2));
00967 }
00968 
00969 void EPSPlug::Curve(FPointArray *i, QString vals)
00970 {
00971        if (vals.isEmpty())
00972               return;
00973        double x1, x2, y1, y2, x3, y3, x4, y4;
00974        x1 = vals.section(' ', 0, 0, QString::SectionSkipEmpty).toDouble();
00975        y1 = vals.section(' ', 1, 1, QString::SectionSkipEmpty).toDouble();
00976        x2 = vals.section(' ', 2, 2, QString::SectionSkipEmpty).toDouble();
00977        y2 = vals.section(' ', 3, 3, QString::SectionSkipEmpty).toDouble();
00978        x3 = vals.section(' ', 4, 4, QString::SectionSkipEmpty).toDouble();
00979        y3 = vals.section(' ', 5, 5, QString::SectionSkipEmpty).toDouble();
00980        x4 = vals.section(' ', 6, 6, QString::SectionSkipEmpty).toDouble();
00981        y4 = vals.section(' ', 7, 7, QString::SectionSkipEmpty).toDouble();
00982        if ((!FirstM) && (WasM))
00983               i->setMarker();
00984        FirstM = false;
00985        WasM = false;
00986        i->addPoint(FPoint(x1, y1));
00987        i->addPoint(FPoint(x2, y2));
00988        i->addPoint(FPoint(x4, y4));
00989        i->addPoint(FPoint(x3, y3));
00990 }
00991 
00992 QString EPSPlug::parseColor(QString vals, bool eps, colorModel model)
00993 {
00994        QString ret = CommonStrings::None;
00995        if (vals.isEmpty())
00996               return ret;
00997        double c, m, y, k, r, g, b;
00998        ScColor tmp;
00999        ColorList::Iterator it;
01000        QTextStream Code(&vals, IO_ReadOnly);
01001        bool found = false;
01002        if (model == colorModelRGB)
01003        {
01004               Code >> r;
01005               Code >> g;
01006               Code >> b;
01007               Code >> Opacity;
01008 // Why adding 0.5 here color values range from 0 to 255 not 1 to 256 ??
01009 /*            int Rc = static_cast<int>(r * 255 + 0.5);
01010               int Gc = static_cast<int>(g * 255 + 0.5);
01011               int Bc = static_cast<int>(b * 255 + 0.5); */
01012               int Rc = qRound(r * 255);
01013               int Gc = qRound(g * 255);
01014               int Bc = qRound(b * 255);
01015               int hR, hG, hB;
01016               tmp.setColorRGB(Rc, Gc, Bc);
01017               for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
01018               {
01019                      if (it.data().getColorModel() == colorModelRGB)
01020                      {
01021                             it.data().getRGB(&hR, &hG, &hB);
01022                             if ((Rc == hR) && (Gc == hG) && (Bc == hB))
01023                             {
01024                                    ret = it.key();
01025                                    found = true;
01026                             }
01027                      }
01028               }
01029        }
01030        else
01031        {
01032               Code >> c;
01033               Code >> m;
01034               Code >> y;
01035               Code >> k;
01036               Code >> Opacity;
01037 /*            int Cc = static_cast<int>(c * 255 + 0.5);
01038               int Mc = static_cast<int>(m * 255 + 0.5);
01039               int Yc = static_cast<int>(y * 255 + 0.5);
01040               int Kc = static_cast<int>(k * 255 + 0.5); */
01041               int Cc = qRound(c * 255);
01042               int Mc = qRound(m * 255);
01043               int Yc = qRound(y * 255);
01044               int Kc = qRound(k * 255);
01045               int hC, hM, hY, hK;
01046               tmp.setColor(Cc, Mc, Yc, Kc);
01047               for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
01048               {
01049                      if (it.data().getColorModel() == colorModelCMYK)
01050                      {
01051                             it.data().getCMYK(&hC, &hM, &hY, &hK);
01052                             if ((Cc == hC) && (Mc == hM) && (Yc == hY) && (Kc == hK))
01053                             {
01054                                    ret = it.key();
01055                                    found = true;
01056                             }
01057                      }
01058               }
01059        }
01060        if (!found)
01061        {
01062               tmp.setSpotColor(false);
01063               tmp.setRegistrationColor(false);
01064               QString namPrefix = "FromEPS";
01065               if (!eps)
01066                      namPrefix = "FromPS";
01067               m_Doc->PageColors.insert(namPrefix+tmp.name(), tmp);
01068               importedColors.append(namPrefix+tmp.name());
01069               ret = namPrefix+tmp.name();
01070        }
01071        return ret;
01072 }