Back to index

scribus-ng  1.3.4.dfsg+svn20071115
oodrawimp.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 <qwidget.h>
00008 #include <qfile.h>
00009 #include <qtextstream.h>
00010 #include <qregexp.h>
00011 #include <qcursor.h>
00012 #include <qdragobject.h>
00013 #include <qdir.h>
00014 #include <qstring.h>
00015 #include <qdom.h>
00016 #include <cmath>
00017 
00018 #include "oodrawimp.h"
00019 #include "oodrawimp.moc"
00020 
00021 #include "scconfig.h"
00022 
00023 #include "scribuscore.h"
00024 #include "scribusdoc.h"
00025 #include "pageitem.h"
00026 #include "fpointarray.h"
00027 #include "customfdialog.h"
00028 #include "commonstrings.h"
00029 #include "color.h"
00030 #include "scribusXml.h"
00031 #include "mpalette.h"
00032 #include "prefsmanager.h"
00033 #include "prefsfile.h"
00034 #include "prefscontext.h"
00035 #include "prefstable.h"
00036 #include "fileunzip.h"
00037 #include "selection.h"
00038 #include "serializer.h"
00039 #include "undomanager.h"
00040 #include "pluginmanager.h"
00041 #include "util.h"
00042 #include "stylestack.h"
00043 #include "scraction.h"
00044 #include "menumanager.h"
00045 #include "sccolorengine.h"
00046 
00047 using namespace std;
00048 
00049 int oodrawimp_getPluginAPIVersion()
00050 {
00051        return PLUGIN_API_VERSION;
00052 }
00053 
00054 ScPlugin* oodrawimp_getPlugin()
00055 {
00056        OODrawImportPlugin* plug = new OODrawImportPlugin();
00057        Q_CHECK_PTR(plug);
00058        return plug;
00059 }
00060 
00061 void oodrawimp_freePlugin(ScPlugin* plugin)
00062 {
00063        OODrawImportPlugin* plug = dynamic_cast<OODrawImportPlugin*>(plugin);
00064        Q_ASSERT(plug);
00065        delete plug;
00066 }
00067 
00068 OODrawImportPlugin::OODrawImportPlugin() :
00069        LoadSavePlugin(),
00070        importAction(new ScrAction(ScrAction::DLL, QIconSet(), "", QKeySequence(), this, "ImportOpenOfficeDraw"))
00071 {
00072        // Set action info in languageChange, so we only have to do
00073        // it in one place. This includes registering file formats.
00074        languageChange();
00075 }
00076 
00077 void OODrawImportPlugin::addToMainWindowMenu(ScribusMainWindow *mw)
00078 {
00079        // Then hook up the action
00080        importAction->setEnabled(true);
00081        connect( importAction, SIGNAL(activated()), SLOT(import()) );
00082        mw->scrMenuMgr->addMenuItem(importAction, "FileImport");
00083 }
00084 
00085 OODrawImportPlugin::~OODrawImportPlugin()
00086 {
00087        unregisterAll();
00088        // note: importAction is automatically deleted by Qt
00089 };
00090 
00091 void OODrawImportPlugin::languageChange()
00092 {
00093        importAction->setMenuText( tr("Import &OpenOffice.org Draw..."));
00094        // (Re)register file formats
00095        unregisterAll();
00096        registerFormats();
00097 }
00098 
00099 const QString OODrawImportPlugin::fullTrName() const
00100 {
00101        return QObject::tr("OpenOffice.org Draw Importer");
00102 }
00103 
00104 const ScActionPlugin::AboutData* OODrawImportPlugin::getAboutData() const
00105 {
00106        AboutData* about = new AboutData;
00107        about->authors = "Franz Schmid <franz@scribus.info>";
00108        about->shortDescription = tr("Imports OpenOffice.org Draw Files");
00109        about->description = tr("Imports most OpenOffice.org Draw files into the current document, converting their vector data into Scribus objects.");
00110        about->license = "GPL";
00111        Q_CHECK_PTR(about);
00112        return about;
00113 }
00114 
00115 void OODrawImportPlugin::deleteAboutData(const AboutData* about) const
00116 {
00117        Q_ASSERT(about);
00118        delete about;
00119 }
00120 
00121 void OODrawImportPlugin::registerFormats()
00122 {
00123        QString odtName = tr("OpenDocument 1.0 Draw", "Import/export format name");
00124        FileFormat odtformat(this);
00125        odtformat.trName = odtName; // Human readable name
00126        odtformat.formatId = FORMATID_ODGIMPORT;
00127        odtformat.filter = odtName + " (*.odg *.ODG)"; // QFileDialog filter
00128        odtformat.nameMatch = QRegExp("\\.odg$", false);
00129        odtformat.load = true;
00130        odtformat.save = false;
00131        odtformat.mimeTypes = QStringList("application/vnd.oasis.opendocument.graphics"); // MIME types
00132        odtformat.priority = 64; // Priority
00133        registerFormat(odtformat);
00134 
00135        QString sxdName = tr("OpenOffice.org 1.x Draw", "Import/export format name");
00136        FileFormat sxdformat(this);
00137        sxdformat.trName = sxdName; // Human readable name
00138        sxdformat.formatId = FORMATID_SXDIMPORT;
00139        sxdformat.filter = sxdName + " (*.sxd *.SXD)"; // QFileDialog filter
00140        sxdformat.nameMatch = QRegExp("\\.sxd$", false);
00141        sxdformat.load = true;
00142        sxdformat.save = false;
00143        sxdformat.mimeTypes = QStringList("application/vnd.sun.xml.draw"); // MIME types
00144        sxdformat.priority = 64; // Priority
00145        registerFormat(sxdformat);
00146 }
00147 
00148 bool OODrawImportPlugin::fileSupported(QIODevice* /* file */, const QString & fileName) const
00149 {
00150        // TODO: try to identify .sxd / .odt files
00151        return true;
00152 }
00153 
00154 bool OODrawImportPlugin::loadFile(const QString & fileName, const FileFormat &, int flags, int /*index*/)
00155 {
00156        // For this plugin, right now "load" and "import" are the same thing
00157        return import(fileName, flags);
00158 }
00159 
00160 bool OODrawImportPlugin::import(QString fileName, int flags)
00161 {
00162        if (!checkFlags(flags))
00163               return false;
00164        if (fileName.isEmpty())
00165        {
00166               flags |= lfInteractive;
00167               PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("OODrawImport");
00168               QString wdir = prefs->get("wdir", ".");
00169               CustomFDialog diaf(ScCore->primaryMainWindow(), wdir, QObject::tr("Open"), QObject::tr("OpenOffice.org Draw (*.sxd *.odg);;All Files (*)"));
00170               if (diaf.exec())
00171               {
00172                      fileName = diaf.selectedFile();
00173                      prefs->set("wdir", fileName.left(fileName.findRev("/")));
00174               }
00175               else
00176                      return true;
00177        }
00178        m_Doc=ScCore->primaryMainWindow()->doc;
00179        if (UndoManager::undoEnabled() && m_Doc)
00180        {
00181               UndoManager::instance()->beginTransaction(m_Doc->currentPage()->getUName(),
00182                                                                                            Um::IImageFrame,
00183                                                                                            Um::ImportOOoDraw,
00184                                                                                            fileName, Um::IImportOOoDraw);
00185        }
00186        else if (UndoManager::undoEnabled() && !m_Doc)
00187               UndoManager::instance()->setUndoEnabled(false);
00188        OODPlug dia(m_Doc);
00189        bool importDone = dia.import(fileName, flags);
00190        if (UndoManager::undoEnabled())
00191               UndoManager::instance()->commit();
00192        else
00193               UndoManager::instance()->setUndoEnabled(true);
00194        if (dia.importCanceled)
00195        {
00196               if ((!importDone) || (dia.importFailed))
00197                      QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, tr("The file could not be imported"), 1, 0, 0);
00198               else if (dia.unsupported)
00199                      QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, tr("This file contains some unsupported features"), 1, 0, 0);
00200        }
00201        return importDone;
00202 }
00203 
00204 OODPlug::OODPlug(ScribusDoc* doc)
00205 {
00206        m_Doc=doc;
00207        unsupported = false;
00208        interactive = false;
00209        importFailed = false;
00210        importCanceled = true;
00211        importedColors.clear();
00212        tmpSel=new Selection(this, false);
00213 }
00214 
00215 bool OODPlug::import( QString fileName, int flags )
00216 {
00217        bool importDone = false;
00218        interactive = (flags & LoadSavePlugin::lfInteractive);
00219        QString f, f2, f3;
00220        if ( !QFile::exists(fileName) )
00221               return false;
00222        m_styles.setAutoDelete( true );
00223        FileUnzip* fun = new FileUnzip(fileName);
00224        stylePath   = fun->getFile("styles.xml");
00225        contentPath = fun->getFile("content.xml");
00226        metaPath = fun->getFile("meta.xml");
00227        delete fun;
00228        if ((stylePath != NULL) && (contentPath != NULL))
00229        {
00230               QString docname = fileName.right(fileName.length() - fileName.findRev("/") - 1);
00231               docname = docname.left(docname.findRev("."));
00232               loadText(stylePath, &f);
00233               if(!inpStyles.setContent(f))
00234                      return false;
00235               loadText(contentPath, &f2);
00236               if(!inpContents.setContent(f2))
00237                      return false;
00238               QFile f1(stylePath);
00239               f1.remove();
00240               QFile f2(contentPath);
00241               f2.remove();
00242               if (metaPath != NULL)
00243               {
00244                      HaveMeta = true;
00245                      loadText(metaPath, &f3);
00246                      if(!inpMeta.setContent(f3))
00247                             HaveMeta = false;
00248                      QFile f3(metaPath);
00249                      f3.remove();
00250               }
00251               else
00252                      HaveMeta = false;
00253        }
00254        else if ((stylePath == NULL) && (contentPath != NULL))
00255        {
00256               QFile f2(contentPath);
00257               f2.remove();
00258        }
00259        else if ((stylePath != NULL) && (contentPath == NULL))
00260        {
00261               QFile f1(stylePath);
00262               f1.remove();
00263        }
00264        QString CurDirP = QDir::currentDirPath();
00265        QFileInfo efp(fileName);
00266        QDir::setCurrent(efp.dirPath());
00267        importDone = convert(flags);
00268        QDir::setCurrent(CurDirP);
00269        return importDone;
00270 }
00271 
00272 bool OODPlug::convert(int flags)
00273 {
00274        bool ret = false;
00275        bool isOODraw2 = false;
00276        QDomNode drawPagePNode;
00277        int PageCounter = 0;
00278        QPtrList<PageItem> Elements;
00279        createStyleMap( inpStyles );
00280        QDomElement docElem = inpContents.documentElement();
00281        QDomNode automaticStyles = docElem.namedItem( "office:automatic-styles" );
00282        if( !automaticStyles.isNull() )
00283               insertStyles( automaticStyles.toElement() );
00284        QDomNode body = docElem.namedItem( "office:body" );
00285        QDomNode drawPage = body.namedItem( "draw:page" );
00286        if ( drawPage.isNull() )
00287        {
00288               QDomNode offDraw = body.namedItem( "office:drawing" );
00289               drawPage = offDraw.namedItem( "draw:page" );
00290               if (drawPage.isNull())
00291               {
00292                      QMessageBox::warning( m_Doc->scMW(), CommonStrings::trWarning, tr("This document does not seem to be an OpenOffice Draw file.") );
00293                      return false;
00294               }
00295               else
00296               {
00297                      isOODraw2 = true;
00298                      drawPagePNode = body.namedItem( "office:drawing" );
00299               }
00300        }
00301        else 
00302               drawPagePNode = body;
00303        StyleStack::Mode mode = isOODraw2 ? StyleStack::OODraw2x : StyleStack::OODraw1x;
00304        m_styleStack.setMode( mode );
00305        QDomElement dp = drawPage.toElement();
00306        QDomElement *master = m_styles[dp.attribute( "draw:master-page-name" )];
00307        QDomElement *style = NULL;
00308        QDomElement properties;
00309        if (isOODraw2)
00310        {
00311               style = m_styles[master->attribute( "style:page-layout-name" )];
00312               properties = style->namedItem( "style:page-layout-properties" ).toElement();
00313        }
00314        else
00315        {
00316               style = m_styles[master->attribute( "style:page-master-name" )];
00317               properties = style->namedItem( "style:properties" ).toElement();
00318        }
00319        double width = !properties.attribute( "fo:page-width" ).isEmpty() ? parseUnit(properties.attribute( "fo:page-width" ) ) : 550.0;
00320        double height = !properties.attribute( "fo:page-height" ).isEmpty() ? parseUnit(properties.attribute( "fo:page-height" ) ) : 841.0;
00321        if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
00322               m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
00323        else
00324        {
00325               if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
00326               {
00327                      m_Doc=ScCore->primaryMainWindow()->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
00328                      ScCore->primaryMainWindow()->HaveNewDoc();
00329                      ret = true;
00330               }
00331        }
00332        if ((ret) || (!interactive))
00333        {
00334               if (width > height)
00335                      m_Doc->PageOri = 1;
00336               else
00337                      m_Doc->PageOri = 0;
00338               m_Doc->m_pageSize = "Custom";
00339               QDomNode mpg;
00340               QDomElement metaElem = inpMeta.documentElement();
00341               QDomElement mp = metaElem.namedItem( "office:meta" ).toElement();
00342               mpg = mp.namedItem( "dc:title" );
00343               if (!mpg.isNull())
00344                      m_Doc->documentInfo.setTitle(QString::fromUtf8(mpg.toElement().text()));
00345               mpg = mp.namedItem( "meta:initial-creator" );
00346               if (!mpg.isNull())
00347                      m_Doc->documentInfo.setAuthor(QString::fromUtf8(mpg.toElement().text()));
00348               mpg = mp.namedItem( "dc:description" );
00349               if (!mpg.isNull())
00350                      m_Doc->documentInfo.setComments(QString::fromUtf8(mpg.toElement().text()));
00351               mpg = mp.namedItem( "dc:language" );
00352               if (!mpg.isNull())
00353                      m_Doc->documentInfo.setLangInfo(QString::fromUtf8(mpg.toElement().text()));
00354               mpg = mp.namedItem( "meta:creation-date" );
00355               if (!mpg.isNull())
00356                      m_Doc->documentInfo.setDate(QString::fromUtf8(mpg.toElement().text()));
00357               mpg = mp.namedItem( "dc:creator" );
00358               if (!mpg.isNull())
00359                      m_Doc->documentInfo.setContrib(QString::fromUtf8(mpg.toElement().text()));
00360               mpg = mp.namedItem( "meta:keywords" );
00361               if (!mpg.isNull())
00362               {
00363                      QString Keys = "";
00364                      for( QDomNode n = mpg.firstChild(); !n.isNull(); n = n.nextSibling() )
00365                      {
00366                             Keys += QString::fromUtf8(n.toElement().text())+", ";
00367                      }
00368                      if (Keys.length() > 2)
00369                             m_Doc->documentInfo.setKeywords(Keys.left(Keys.length()-2));
00370               }
00371        }
00372        FPoint minSize = m_Doc->minCanvasCoordinate;
00373        FPoint maxSize = m_Doc->maxCanvasCoordinate;
00374        m_Doc->view()->Deselect();
00375        Elements.clear();
00376        m_Doc->setLoading(true);
00377        m_Doc->DoDrawing = false;
00378        m_Doc->view()->updatesOn(false);
00379        m_Doc->scMW()->ScriptRunning = true;
00380        qApp->setOverrideCursor(QCursor(Qt::waitCursor), true);
00381        m_Doc->PageColors.ensureBlackAndWhite();
00382        for( QDomNode drawPag = drawPagePNode.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling() )
00383        {
00384               QDomElement dpg = drawPag.toElement();
00385               if (!interactive)
00386               {
00387                      m_Doc->addPage(PageCounter);
00388                      m_Doc->view()->addPage(PageCounter);
00389               }
00390               PageCounter++;
00391               m_styleStack.clear();
00392               fillStyleStack( dpg );
00393               QPtrList<PageItem> el = parseGroup( dpg );
00394               for (uint ec = 0; ec < el.count(); ++ec)
00395                      Elements.append(el.at(ec));
00396               if ((interactive) && (PageCounter == 1))
00397                      break;
00398        }
00399        tmpSel->clear();
00400 //     if ((Elements.count() > 1) && (interactive))
00401        if (Elements.count() == 0)
00402        {
00403               importFailed = true;
00404               if (importedColors.count() != 0)
00405               {
00406                      for (uint cd = 0; cd < importedColors.count(); cd++)
00407                      {
00408                             m_Doc->PageColors.remove(importedColors[cd]);
00409                      }
00410               }
00411        }
00412        if (Elements.count() > 1)
00413        {
00414               bool isGroup = true;
00415               int firstElem = -1;
00416               if (Elements.at(0)->Groups.count() != 0)
00417                      firstElem = Elements.at(0)->Groups.top();
00418               for (uint bx = 0; bx < Elements.count(); ++bx)
00419               {
00420                      PageItem* bxi = Elements.at(bx);
00421                      if (bxi->Groups.count() != 0)
00422                      {
00423                             if (bxi->Groups.top() != firstElem)
00424                                    isGroup = false;
00425                      }
00426                      else
00427                             isGroup = false;
00428               }
00429               if (!isGroup)
00430               {
00431                      double minx = 99999.9;
00432                      double miny = 99999.9;
00433                      double maxx = -99999.9;
00434                      double maxy = -99999.9;
00435                      uint lowestItem = 999999;
00436                      uint highestItem = 0;
00437                      for (uint a = 0; a < Elements.count(); ++a)
00438                      {
00439                             Elements.at(a)->Groups.push(m_Doc->GroupCounter);
00440                             PageItem* currItem = Elements.at(a);
00441                             lowestItem = QMIN(lowestItem, currItem->ItemNr);
00442                             highestItem = QMAX(highestItem, currItem->ItemNr);
00443                             double lw = currItem->lineWidth() / 2.0;
00444                             if (currItem->rotation() != 0)
00445                             {
00446                                    FPointArray pb;
00447                                    pb.resize(0);
00448                                    pb.addPoint(FPoint(currItem->xPos()-lw, currItem->yPos()-lw));
00449                                    pb.addPoint(FPoint(currItem->width()+lw*2.0, -lw, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00450                                    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));
00451                                    pb.addPoint(FPoint(-lw, currItem->height()+lw*2.0, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00452                                    for (uint pc = 0; pc < 4; ++pc)
00453                                    {
00454                                           minx = QMIN(minx, pb.point(pc).x());
00455                                           miny = QMIN(miny, pb.point(pc).y());
00456                                           maxx = QMAX(maxx, pb.point(pc).x());
00457                                           maxy = QMAX(maxy, pb.point(pc).y());
00458                                    }
00459                             }
00460                             else
00461                             {
00462                                    minx = QMIN(minx, currItem->xPos()-lw);
00463                                    miny = QMIN(miny, currItem->yPos()-lw);
00464                                    maxx = QMAX(maxx, currItem->xPos()-lw + currItem->width()+lw*2.0);
00465                                    maxy = QMAX(maxy, currItem->yPos()-lw + currItem->height()+lw*2.0);
00466                             }
00467                      }
00468                      double gx = minx;
00469                      double gy = miny;
00470                      double gw = maxx - minx;
00471                      double gh = maxy - miny;
00472                      PageItem *high = m_Doc->Items->at(highestItem);
00473                      int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->toolSettings.dBrush, m_Doc->toolSettings.dPen, true);
00474                      PageItem *neu = m_Doc->Items->take(z);
00475                      m_Doc->Items->insert(lowestItem, neu);
00476                      neu->Groups.push(m_Doc->GroupCounter);
00477                      neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
00478                      neu->isGroupControl = true;
00479                      neu->groupsLastItem = high;
00480                      neu->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00481                      for (uint a = 0; a < m_Doc->Items->count(); ++a)
00482                      {
00483                             m_Doc->Items->at(a)->ItemNr = a;
00484                      }
00485                      Elements.prepend(neu);
00486                      m_Doc->GroupCounter++;
00487               }
00488        }
00489        m_Doc->DoDrawing = true;
00490        m_Doc->scMW()->ScriptRunning = false;
00491        if (interactive)
00492               m_Doc->setLoading(false);
00493        qApp->setOverrideCursor(QCursor(Qt::arrowCursor), true);
00494        if ((Elements.count() > 0) && (!ret) && (interactive))
00495        {
00496               if (flags & LoadSavePlugin::lfScripted)
00497               {
00498                      bool loadF = m_Doc->isLoading();
00499                      m_Doc->setLoading(false);
00500                      m_Doc->changed();
00501                      m_Doc->setLoading(loadF);
00502                      for (uint dre=0; dre<Elements.count(); ++dre)
00503                      {
00504                             m_Doc->m_Selection->addItem(Elements.at(dre), true);
00505                      }
00506                      m_Doc->m_Selection->setGroupRect();
00507                      m_Doc->view()->updatesOn(true);
00508                      importCanceled = false;
00509               }
00510               else
00511               {
00512                      m_Doc->DragP = true;
00513                      m_Doc->DraggedElem = 0;
00514                      m_Doc->DragElements.clear();
00515                      for (uint dre=0; dre<Elements.count(); ++dre)
00516                      {
00517                             m_Doc->DragElements.append(Elements.at(dre)->ItemNr);
00518                             tmpSel->addItem(Elements.at(dre), true);
00519                      }
00520                      ScriXmlDoc *ss = new ScriXmlDoc();
00521                      tmpSel->setGroupRect();
00522                      QDragObject *dr = new QTextDrag(ss->WriteElem(m_Doc, m_Doc->view(), tmpSel), m_Doc->view()->viewport());
00523 #ifndef QT_MAC
00524 // see #2196, #2526
00525                      m_Doc->itemSelection_DeleteItem(tmpSel);
00526 #endif
00527                      m_Doc->view()->resizeContents(qRound((maxSize.x() - minSize.x()) * m_Doc->view()->scale()), qRound((maxSize.y() - minSize.y()) * m_Doc->view()->scale()));
00528                      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()));
00529                      m_Doc->minCanvasCoordinate = minSize;
00530                      m_Doc->maxCanvasCoordinate = maxSize;
00531                      m_Doc->view()->updatesOn(true);
00532                      dr->setPixmap(loadIcon("DragPix.xpm"));
00533                      dr->drag();
00534                      /*importCanceled = dr->drag();
00535                      if (!importCanceled)
00536                      {
00537                             if (importedColors.count() != 0)
00538                             {
00539                                    for (uint cd = 0; cd < importedColors.count(); cd++)
00540                                    {
00541                                           m_Doc->PageColors.remove(importedColors[cd]);
00542                                    }
00543                             }
00544                      }*/
00545                      delete ss;
00546                      m_Doc->DragP = false;
00547                      m_Doc->DraggedElem = 0;
00548                      m_Doc->DragElements.clear();
00549               }
00550        }
00551        else
00552        {
00553               bool loadF = m_Doc->isLoading();
00554               m_Doc->setLoading(false);
00555               m_Doc->changed();
00556               m_Doc->reformPages();
00557               m_Doc->view()->updatesOn(true);
00558               m_Doc->setLoading(loadF);
00559        }
00560        return true;
00561 }
00562 
00563 QPtrList<PageItem> OODPlug::parseGroup(const QDomElement &e)
00564 {
00565        OODrawStyle oostyle;
00566        FPointArray ImgClip;
00567        QPtrList<PageItem> elements, cElements;
00568        double BaseX = m_Doc->currentPage()->xOffset();
00569        double BaseY = m_Doc->currentPage()->yOffset();
00570        storeObjectStyles(e);
00571        parseStyle(oostyle, e);
00572        QString drawID = e.attribute("draw:name");
00573        int zn = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, 1, 1, 0, CommonStrings::None, CommonStrings::None, true);
00574        PageItem *neu = m_Doc->Items->at(zn);
00575        for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
00576        {
00577               QDomElement b = n.toElement();
00578               if( b.isNull() )
00579                      continue;
00580               QPtrList<PageItem> el = parseElement(b);
00581               for (uint ec = 0; ec < el.count(); ++ec)
00582                      cElements.append(el.at(ec));
00583        }
00584        if (cElements.count() < 2)
00585        {
00586               m_Doc->Items->take(zn);
00587               delete neu;
00588               for (uint a = 0; a < m_Doc->Items->count(); ++a)
00589               {
00590                      m_Doc->Items->at(a)->ItemNr = a;
00591               }
00592               for (uint gr = 0; gr < cElements.count(); ++gr)
00593               {
00594                      elements.append(cElements.at(gr));
00595               }
00596        }
00597        else
00598        {
00599               double minx = 99999.9;
00600               double miny = 99999.9;
00601               double maxx = -99999.9;
00602               double maxy = -99999.9;
00603               elements.append(neu);
00604               for (uint gr = 0; gr < cElements.count(); ++gr)
00605               {
00606                      PageItem* currItem = cElements.at(gr);
00607                      double lw = currItem->lineWidth() / 2.0;
00608                      if (currItem->rotation() != 0)
00609                      {
00610                             FPointArray pb;
00611                             pb.resize(0);
00612                             pb.addPoint(FPoint(currItem->xPos()-lw, currItem->yPos()-lw));
00613                             pb.addPoint(FPoint(currItem->width()+lw*2.0, -lw, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00614                             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));
00615                             pb.addPoint(FPoint(-lw, currItem->height()+lw*2.0, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00616                             for (uint pc = 0; pc < 4; ++pc)
00617                             {
00618                                    minx = QMIN(minx, pb.point(pc).x());
00619                                    miny = QMIN(miny, pb.point(pc).y());
00620                                    maxx = QMAX(maxx, pb.point(pc).x());
00621                                    maxy = QMAX(maxy, pb.point(pc).y());
00622                             }
00623                      }
00624                      else
00625                      {
00626                             minx = QMIN(minx, currItem->xPos()-lw);
00627                             miny = QMIN(miny, currItem->yPos()-lw);
00628                             maxx = QMAX(maxx, currItem->xPos()-lw + currItem->width()+lw*2.0);
00629                             maxy = QMAX(maxy, currItem->yPos()-lw + currItem->height()+lw*2.0);
00630                      }
00631               }
00632               double gx = minx;
00633               double gy = miny;
00634               double gw = maxx - minx;
00635               double gh = maxy - miny;
00636               neu->setXYPos(gx, gy);
00637               neu->setWidthHeight(gw, gh);
00638               if (ImgClip.size() != 0)
00639                      neu->PoLine = ImgClip.copy();
00640               else
00641                      neu->SetRectFrame();
00642               ImgClip.resize(0);
00643               neu->Clip = FlattenPath(neu->PoLine, neu->Segments);
00644               neu->Groups.push(m_Doc->GroupCounter);
00645               neu->isGroupControl = true;
00646               neu->groupsLastItem = cElements.at(cElements.count()-1);
00647               if( !e.attribute("id").isEmpty() )
00648                      neu->setItemName(e.attribute("id"));
00649               else
00650                      neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
00651 //            neu->setFillTransparency(1 - gc->Opacity);
00652               for (uint gr = 0; gr < cElements.count(); ++gr)
00653               {
00654                      cElements.at(gr)->Groups.push(m_Doc->GroupCounter);
00655                      elements.append(cElements.at(gr));
00656               }
00657               neu->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00658               m_Doc->GroupCounter++;
00659        }
00660        return elements;
00661 }
00662 
00663 QPtrList<PageItem> OODPlug::parseElement(const QDomElement &e)
00664 {
00665        QPtrList<PageItem> GElements;
00666        QString STag = e.tagName();
00667        if ( STag == "draw:g" )
00668        {
00669               GElements = parseGroup(e);
00670               return GElements;
00671        }
00672        if ( STag == "draw:rect" )
00673               GElements = parseRect(e);
00674        else if ( STag == "draw:circle" || STag == "draw:ellipse" )
00675               GElements = parseEllipse(e);
00676        else if ( STag == "draw:line" )
00677               GElements = parseLine(e);
00678        else if ( STag == "draw:polygon" )
00679               GElements = parsePolygon(e);
00680        else if ( STag == "draw:polyline" )
00681               GElements = parsePolyline(e);
00682        else if( STag == "draw:path" )
00683               GElements = parsePath(e);
00684        else if ( STag == "draw:text-box" )
00685               GElements = parseTextBox(e);
00686        else if ( STag == "draw:frame" )
00687               GElements = parseFrame(e);
00688        else if ( STag == "draw:connector" )
00689               GElements = parseConnector(e);
00690        else
00691        {
00692               // warn if unsupported feature are encountered
00693               unsupported = true;
00694               qDebug("Not supported yet: %s", STag.local8Bit().data());
00695        }
00696        return GElements;
00697 }
00698 
00699 QPtrList<PageItem> OODPlug::parseRect(const QDomElement &e)
00700 {
00701        OODrawStyle style;
00702        QPtrList<PageItem> elements;
00703        double BaseX = m_Doc->currentPage()->xOffset();
00704        double BaseY = m_Doc->currentPage()->yOffset();
00705        double x = parseUnit(e.attribute("svg:x"));
00706        double y = parseUnit(e.attribute("svg:y")) ;
00707        double w = parseUnit(e.attribute("svg:width"));
00708        double h = parseUnit(e.attribute("svg:height"));
00709        double corner = parseUnit(e.attribute("draw:corner-radius"));
00710        storeObjectStyles(e);
00711        parseStyle(style, e);
00712        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX+x, BaseY+y, w, h, style.strokeWidth, style.fillColor, style.strokeColor, true);
00713        PageItem* ite = m_Doc->Items->at(z);
00714        if (corner != 0)
00715        {
00716               ite->setCornerRadius(corner);
00717               ite->SetFrameRound();
00718               m_Doc->setRedrawBounding(ite);
00719        }
00720        ite = finishNodeParsing(e, ite, style);
00721        elements.append(ite);
00722        return elements;
00723 }
00724 
00725 QPtrList<PageItem> OODPlug::parseEllipse(const QDomElement &e)
00726 {
00727        OODrawStyle style;
00728        QPtrList<PageItem> elements;
00729        double BaseX = m_Doc->currentPage()->xOffset();
00730        double BaseY = m_Doc->currentPage()->yOffset();
00731        double x = parseUnit(e.attribute("svg:x"));
00732        double y = parseUnit(e.attribute("svg:y")) ;
00733        double w = parseUnit(e.attribute("svg:width"));
00734        double h = parseUnit(e.attribute("svg:height"));
00735        storeObjectStyles(e);
00736        parseStyle(style, e);
00737        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX+x, BaseY+y, w, h, style.strokeWidth, style.fillColor, style.strokeColor, true);
00738        PageItem* ite = m_Doc->Items->at(z);
00739        ite = finishNodeParsing(e, ite, style);
00740        elements.append(ite);
00741        return elements;
00742 }
00743 
00744 QPtrList<PageItem> OODPlug::parseLine(const QDomElement &e)
00745 {
00746        OODrawStyle style;
00747        QPtrList<PageItem> elements;
00748        double BaseX = m_Doc->currentPage()->xOffset();
00749        double BaseY = m_Doc->currentPage()->yOffset();
00750        double x1 = e.attribute( "svg:x1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:x1" ) );
00751        double y1 = e.attribute( "svg:y1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:y1" ) );
00752        double x2 = e.attribute( "svg:x2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:x2" ) );
00753        double y2 = e.attribute( "svg:y2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:y2" ) );
00754        storeObjectStyles(e);
00755        parseStyle(style, e);
00756        int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, style.strokeWidth, CommonStrings::None, style.strokeColor, true);
00757        PageItem* ite = m_Doc->Items->at(z);
00758        ite->PoLine.resize(4);
00759        ite->PoLine.setPoint(0, FPoint(x1, y1));
00760        ite->PoLine.setPoint(1, FPoint(x1, y1));
00761        ite->PoLine.setPoint(2, FPoint(x2, y2));
00762        ite->PoLine.setPoint(3, FPoint(x2, y2));
00763        FPoint wh = getMaxClipF(&ite->PoLine);
00764        ite->setWidthHeight(wh.x(), wh.y());
00765        ite->ClipEdited = true;
00766        ite->FrameType = 3;
00767        if (!e.hasAttribute("draw:transform"))
00768        {
00769               ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00770               m_Doc->AdjustItemSize(ite);
00771        }
00772        ite = finishNodeParsing(e, ite, style);
00773        elements.append(ite);
00774        return elements;
00775 }
00776 
00777 QPtrList<PageItem> OODPlug::parsePolygon(const QDomElement &e)
00778 {
00779        OODrawStyle style;
00780        QPtrList<PageItem> elements;
00781        double BaseX = m_Doc->currentPage()->xOffset();
00782        double BaseY = m_Doc->currentPage()->yOffset();
00783        storeObjectStyles(e);
00784        parseStyle(style, e);
00785        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, style.strokeWidth, style.fillColor, style.strokeColor, true);
00786        PageItem* ite = m_Doc->Items->at(z);
00787        ite->PoLine.resize(0);
00788        appendPoints(&ite->PoLine, e);
00789        FPoint wh = getMaxClipF(&ite->PoLine);
00790        ite->setWidthHeight(wh.x(), wh.y());
00791        ite->ClipEdited = true;
00792        ite->FrameType = 3;
00793        if (!e.hasAttribute("draw:transform"))
00794        {
00795               ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00796               m_Doc->AdjustItemSize(ite);
00797        }
00798        ite = finishNodeParsing(e, ite, style);
00799        elements.append(ite);
00800        return elements;
00801 }
00802 
00803 QPtrList<PageItem> OODPlug::parsePolyline(const QDomElement &e)
00804 {
00805        OODrawStyle style;
00806        QPtrList<PageItem> elements;
00807        double BaseX = m_Doc->currentPage()->xOffset();
00808        double BaseY = m_Doc->currentPage()->yOffset();
00809        storeObjectStyles(e);
00810        parseStyle(style, e);
00811        int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, style.strokeWidth, CommonStrings::None, style.strokeColor, true);
00812        PageItem* ite = m_Doc->Items->at(z);
00813        ite->PoLine.resize(0);
00814        appendPoints(&ite->PoLine, e);
00815        FPoint wh = getMaxClipF(&ite->PoLine);
00816        ite->setWidthHeight(wh.x(), wh.y());
00817        ite->ClipEdited = true;
00818        ite->FrameType = 3;
00819        if (!e.hasAttribute("draw:transform"))
00820        {
00821               ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00822               m_Doc->AdjustItemSize(ite);
00823        }
00824        ite = finishNodeParsing(e, ite, style);
00825        elements.append(ite);
00826        return elements;
00827 }
00828 
00829 QPtrList<PageItem> OODPlug::parsePath(const QDomElement &e)
00830 {
00831        OODrawStyle style;
00832        FPointArray pArray;
00833        QPtrList<PageItem> elements;
00834        double BaseX = m_Doc->currentPage()->xOffset();
00835        double BaseY = m_Doc->currentPage()->yOffset();
00836        storeObjectStyles(e);
00837        parseStyle(style, e);
00838        PageItem::ItemType itype = parseSVG(e.attribute("svg:d"), &pArray) ? PageItem::PolyLine : PageItem::Polygon;
00839        int z = m_Doc->itemAdd(itype, PageItem::Unspecified, BaseX, BaseY, 10, 10, style.strokeWidth, style.fillColor, style.strokeColor, true);
00840        PageItem* ite = m_Doc->Items->at(z);
00841        ite->PoLine.resize(0);
00842        ite->PoLine = pArray;
00843        if (ite->PoLine.size() < 4)
00844        {
00845 //            m_Doc->m_Selection->addItem(ite);
00846               tmpSel->addItem(ite);
00847 //            m_Doc->itemSelection_DeleteItem();
00848               m_Doc->itemSelection_DeleteItem(tmpSel);
00849        }
00850        else
00851        {
00852               double x = parseUnit(e.attribute("svg:x"));
00853               double y = parseUnit(e.attribute("svg:y")) ;
00854               double w = parseUnit(e.attribute("svg:width"));
00855               double h = parseUnit(e.attribute("svg:height"));
00856               double vx = 0;
00857               double vy = 0;
00858               double vw = 1;
00859               double vh = 1;
00860               parseViewBox(e, &vx, &vy, &vw, &vh);
00861               QWMatrix mat;
00862               mat.translate(x, y);
00863               mat.scale(w / vw, h / vh);
00864               ite->PoLine.map(mat);
00865               FPoint wh = getMaxClipF(&ite->PoLine);
00866               ite->setWidthHeight(wh.x(), wh.y());
00867               ite->ClipEdited = true;
00868               ite->FrameType = 3;
00869               if (!e.hasAttribute("draw:transform"))
00870               {
00871                      ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
00872                      m_Doc->AdjustItemSize(ite);
00873               }
00874               ite = finishNodeParsing(e, ite, style);
00875               elements.append(ite);
00876        }
00877        return elements;
00878 }
00879 
00880 QPtrList<PageItem> OODPlug::parseTextBox(const QDomElement &e)
00881 {
00882        OODrawStyle style;
00883        QPtrList<PageItem> elements;
00884        double BaseX = m_Doc->currentPage()->xOffset();
00885        double BaseY = m_Doc->currentPage()->yOffset();
00886        double x = parseUnit(e.attribute("svg:x"));
00887        double y = parseUnit(e.attribute("svg:y")) ;
00888        double w = parseUnit(e.attribute("svg:width"));
00889        double h = parseUnit(e.attribute("svg:height"));
00890        storeObjectStyles(e);
00891        parseStyle(style, e);
00892        int z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, BaseX+x, BaseY+y, w, h+(h*0.1), style.strokeWidth, CommonStrings::None, style.strokeColor, true);
00893        PageItem* ite = m_Doc->Items->at(z);
00894        ite->setFillColor(style.fillColor);
00895        ite->setLineColor(style.strokeColor);
00896        ite = finishNodeParsing(e, ite, style);
00897        elements.append(ite);
00898        return elements;
00899 }
00900 
00901 QPtrList<PageItem> OODPlug::parseFrame(const QDomElement &e)
00902 {
00903        OODrawStyle oostyle;
00904        QPtrList<PageItem> elements;
00905        QString drawID = e.attribute("draw:name");
00906        double BaseX = m_Doc->currentPage()->xOffset();
00907        double BaseY = m_Doc->currentPage()->yOffset();
00908        double x = parseUnit(e.attribute("svg:x"));
00909        double y = parseUnit(e.attribute("svg:y")) ;
00910        double w = parseUnit(e.attribute("svg:width"));
00911        double h = parseUnit(e.attribute("svg:height"));
00912        storeObjectStyles(e);
00913        parseStyle(oostyle, e);
00914        QDomNode n = e.firstChild();
00915        QString STag2 = n.toElement().tagName();
00916        if ( STag2 == "draw:text-box" )
00917        {
00918               int z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, BaseX+x, BaseY+y, w, h+(h*0.1), oostyle.strokeWidth, CommonStrings::None, oostyle.strokeColor, true);
00919               PageItem* ite = m_Doc->Items->at(z);
00920               ite->setTextToFrameDist(0.0, 0.0, 0.0, 0.0);
00921               ite->setFillTransparency(oostyle.fillTrans);
00922               ite->setLineTransparency(oostyle.strokeTrans);
00923               ite->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00924               if (!drawID.isEmpty())
00925                      ite->setItemName(drawID);
00926               ite = parseTextP(n.toElement(), ite);
00927               elements.append(ite);
00928        }
00929        return elements;
00930 }
00931 
00932 QPtrList<PageItem> OODPlug::parseConnector(const QDomElement &e)
00933 {
00934        QPtrList<PageItem> elements;
00935        if (e.hasAttribute("svg:x1") && e.hasAttribute("svg:x2") && e.hasAttribute("svg:y1") && e.hasAttribute("svg:y2"))
00936        {
00937               elements = parseLine(e);
00938        }
00939        else
00940        {
00941               unsupported = true;
00942               qDebug("an unsupported form of connector was found");
00943        }
00944        return elements;
00945 }
00946 
00947 void OODPlug::parseStyle(OODrawStyle& oostyle, const QDomElement &e)
00948 {
00949        oostyle.haveGradient = false;
00950        oostyle.gradient.clearStops();
00951        if( m_styleStack.hasAttribute("draw:stroke") )
00952        {
00953               if( m_styleStack.attribute( "draw:stroke" ) == "none" )
00954                      oostyle.strokeWidth = 0.0;
00955               else
00956               {
00957                      if( m_styleStack.hasAttribute("svg:stroke-width"))
00958                      {
00959                             oostyle.strokeWidth = parseUnit(m_styleStack.attribute("svg:stroke-width"));
00960                             if (oostyle.strokeWidth == 0)
00961                                    oostyle.strokeWidth = 1;
00962                      }
00963                      if( m_styleStack.hasAttribute("svg:stroke-color"))
00964                             oostyle.strokeColor = parseColor(m_styleStack.attribute("svg:stroke-color"));
00965                      if( m_styleStack.hasAttribute( "svg:stroke-opacity" ) )
00966                             oostyle.strokeTrans = m_styleStack.attribute( "svg:stroke-opacity" ).remove( '%' ).toDouble() / 100.0;
00967                      if( m_styleStack.attribute( "draw:stroke" ) == "dash" )
00968                      {
00969                             QString style = m_styleStack.attribute( "draw:stroke-dash" );
00970                             if( style == "Ultrafine Dashed")
00971                                    oostyle.dashes << 1.4 << 1.4;
00972                             else if( style == "Fine Dashed" )
00973                                    oostyle.dashes << 14.4 << 14.4;
00974                             else if( style == "Fine Dotted")
00975                                    oostyle.dashes << 13 << 13;
00976                             else if( style == "Ultrafine 2 Dots 3 Dashes")
00977                                    oostyle.dashes << 1.45 << 3.6 << 1.45 << 3.6 << 7.2 << 3.6 << 7.2 << 3.6 << 7.2 << 3.6;
00978                             else if( style == "Line with Fine Dots")
00979                             {
00980                                    oostyle.dashes << 56.9 << 4.31;
00981                                    for (int dd = 0; dd < 10; ++ dd)
00982                                    {
00983                                           oostyle.dashes << 8.6 << 4.31;
00984                                    }
00985                             }
00986                             else if( style == "2 Dots 1 Dash" )
00987                                    oostyle.dashes << 2.8 << 5.75 << 2.8 << 5.75 << 5.75 << 5.75;
00988                      }
00989               }
00990        }
00991        if( m_styleStack.hasAttribute( "draw:fill" ) )
00992        {
00993               QString fill = m_styleStack.attribute( "draw:fill" );
00994               if( fill == "solid" )
00995               {
00996                      if( m_styleStack.hasAttribute( "draw:fill-color" ) )
00997                             oostyle.fillColor = parseColor( m_styleStack.attribute("draw:fill-color"));
00998                      if( m_styleStack.hasAttribute( "draw:transparency" ) )
00999                             oostyle.fillTrans = m_styleStack.attribute( "draw:transparency" ).remove( '%' ).toDouble() / 100.0;
01000               }
01001               else if( fill == "gradient" )
01002               {
01003                      oostyle.haveGradient = true;
01004                      oostyle.gradientAngle = 0;
01005                      oostyle.gradient.clearStops();
01006                      oostyle.gradient.setRepeatMethod( VGradient::none );
01007                      QString style = m_styleStack.attribute( "draw:fill-gradient-name" );
01008                      QDomElement* draw = m_draws[style];
01009                      if( draw )
01010                      {
01011                             double border = 0.0;
01012                             int shadeS = 100;
01013                             int shadeE = 100;
01014                             if( draw->hasAttribute( "draw:border" ) )
01015                                    border += draw->attribute( "draw:border" ).remove( '%' ).toDouble() / 100.0;
01016                             if( draw->hasAttribute( "draw:start-intensity" ) )
01017                                    shadeS = draw->attribute( "draw:start-intensity" ).remove( '%' ).toInt();
01018                             if( draw->hasAttribute( "draw:end-intensity" ) )
01019                                    shadeE = draw->attribute( "draw:end-intensity" ).remove( '%' ).toInt();
01020                             QString type = draw->attribute( "draw:style" );
01021                             if( type == "linear" || type == "axial" )
01022                             {
01023                                    oostyle.gradient.setType( VGradient::linear );
01024                                    oostyle.gradientAngle = draw->attribute( "draw:angle" ).toDouble() / 10;
01025                                    oostyle.gradientType = 1;
01026                             }
01027                             else if( type == "radial" || type == "ellipsoid" )
01028                             {
01029                                    if( draw->hasAttribute( "draw:cx" ) )
01030                                           oostyle.gradientPointX = draw->attribute( "draw:cx" ).remove( '%' ).toDouble() / 100.0;
01031                                    else
01032                                           oostyle.gradientPointX = 0.5;
01033                                    if( draw->hasAttribute( "draw:cy" ) )
01034                                           oostyle.gradientPointY = draw->attribute( "draw:cy" ).remove( '%' ).toDouble() / 100.0;
01035                                    else
01036                                           oostyle.gradientPointY = 0.5;
01037                                    oostyle.gradientType = 2;
01038                             }
01039                             QString c, c2;
01040                             c = parseColor( draw->attribute( "draw:start-color" ) );
01041                             c2 = parseColor( draw->attribute( "draw:end-color" ) );
01042                             const ScColor& col1 = m_Doc->PageColors[c];
01043                             const ScColor& col2 = m_Doc->PageColors[c2];
01044                             if (((oostyle.gradientAngle > 90) && (oostyle.gradientAngle < 271)) || (oostyle.gradientType == 2))
01045                             {
01046                                    const ScColor& col1 = m_Doc->PageColors[c];
01047                                    const ScColor& col2 = m_Doc->PageColors[c2];
01048                                    oostyle.gradient.addStop( ScColorEngine::getRGBColor(col2, m_Doc), 0.0, 0.5, 1, c2, shadeE );
01049                                    oostyle.gradient.addStop( ScColorEngine::getRGBColor(col1, m_Doc), 1.0 - border, 0.5, 1, c, shadeS );
01050                             }
01051                             else
01052                             {
01053                                    oostyle.gradient.addStop( ScColorEngine::getRGBColor(col1, m_Doc), border, 0.5, 1, c, shadeS );
01054                                    oostyle.gradient.addStop( ScColorEngine::getRGBColor(col2, m_Doc), 1.0, 0.5, 1, c2, shadeE );
01055                             }
01056                      }
01057               }
01058        }
01059 }
01060 
01061 void OODPlug::parseCharStyle(CharStyle& style, const QDomElement &e)
01062 {
01063        if ( m_styleStack.hasAttribute("fo:font-size") )
01064        {
01065               QString fs = m_styleStack.attribute("fo:font-size").remove( "pt" );
01066               int FontSize = (int) (fs.toFloat() * 10.0);
01067               style.setFontSize(FontSize);
01068        }
01069 }
01070 
01071 void OODPlug::parseParagraphStyle(ParagraphStyle& style, const QDomElement &e)
01072 {
01073        if ( m_styleStack.hasAttribute("fo:text-align") )
01074        {
01075               QString attValue = m_styleStack.attribute("fo:text-align");
01076               if (attValue == "left")
01077                      style.setAlignment(ParagraphStyle::Leftaligned);
01078               if (attValue == "center")
01079                      style.setAlignment(ParagraphStyle::Centered);
01080               if (attValue == "right")
01081                      style.setAlignment(ParagraphStyle::Rightaligned);
01082        }
01083        if ( m_styleStack.hasAttribute("fo:font-size") )
01084        {
01085               QString fs = m_styleStack.attribute("fo:font-size").remove( "pt" );
01086               int FontSize = (int) (fs.toFloat() * 10.0);
01087               style.charStyle().setFontSize(FontSize);
01088               style.setLineSpacing((FontSize + FontSize * 0.2) / 10.0);
01089        }
01090 }
01091 
01092 PageItem* OODPlug::parseTextP (const QDomElement& elm, PageItem* item)
01093 {
01094        for ( QDomNode n = elm.firstChild(); !n.isNull(); n = n.nextSibling() )
01095        {
01096               if ( !n.hasAttributes() && !n.hasChildNodes() )
01097                      continue;
01098               QDomElement e = n.toElement();
01099               if ( e.text().isEmpty() )
01100                      continue;
01101               storeObjectStyles(e);
01102               item->itemText.insertChars(-1, SpecialChars::PARSEP);
01103               if (e.hasChildNodes())
01104                      item = parseTextSpans(e, item);
01105               else
01106               {
01107                      if ( m_styleStack.hasAttribute("fo:text-align") || m_styleStack.hasAttribute("fo:font-size") )
01108                      {
01109                             ParagraphStyle newStyle;
01110                             parseParagraphStyle(newStyle, e);
01111                             item->itemText.applyStyle(-1, newStyle);
01112                      }
01113                      item->itemText.insertChars(-2, QString::fromUtf8(e.text()) );
01114                      if (!item->asPolyLine() && !item->asTextFrame())
01115                             item = m_Doc->convertItemTo(item, PageItem::TextFrame);
01116               }
01117               
01118        }
01119        return item;
01120 }
01121 
01122 PageItem* OODPlug::parseTextSpans(const QDomElement& elm, PageItem* item)
01123 {
01124        bool firstSpan = true;
01125        for ( QDomNode n = elm.firstChild(); !n.isNull(); n = n.nextSibling() )
01126        {
01127               QDomElement e = n.toElement();
01128               QString sTag = e.tagName();
01129               if (e.text().isEmpty() || sTag != "text:span")
01130                      continue;
01131               storeObjectStyles(e);
01132               QString chars = e.text();
01133               int pos = item->itemText.length();
01134               if ( firstSpan && (m_styleStack.hasAttribute("fo:text-align") || m_styleStack.hasAttribute("fo:font-size")) )
01135               {
01136                      ParagraphStyle newStyle;
01137                      parseParagraphStyle(newStyle, e);
01138                      item->itemText.applyStyle(-1, newStyle);
01139               }
01140               item->itemText.insertChars( -2, chars);
01141               if ( !firstSpan && m_styleStack.hasAttribute("fo:font-size") )
01142               {
01143                      CharStyle newStyle;
01144                      parseCharStyle(newStyle, e);
01145                      item->itemText.applyCharStyle(pos, chars.length(), newStyle);
01146               }
01147               if (!item->asPolyLine() && !item->asTextFrame())
01148                      item = m_Doc->convertItemTo(item, PageItem::TextFrame);
01149               firstSpan = false;
01150        }
01151        return item;
01152 }
01153 
01154 PageItem* OODPlug::finishNodeParsing(const QDomElement &elm, PageItem* item, OODrawStyle& oostyle)
01155 {
01156        item->setTextToFrameDist(0.0, 0.0, 0.0, 0.0);
01157 //     bool firstPa = false;
01158        QString drawID = elm.attribute("draw:name");
01159        item = parseTextP(elm, item);
01160        item->setFillTransparency(oostyle.fillTrans);
01161        item->setLineTransparency(oostyle.strokeTrans);
01162        if (oostyle.dashes.count() != 0)
01163               item->DashValues = oostyle.dashes;
01164        if (!drawID.isEmpty())
01165               item->setItemName(drawID);
01166        if (elm.hasAttribute("draw:transform"))
01167        {
01168               parseTransform(&item->PoLine, elm.attribute("draw:transform"));
01169               item->ClipEdited = true;
01170               item->FrameType = 3;
01171               FPoint wh = getMaxClipF(&item->PoLine);
01172               item->setWidthHeight(wh.x(), wh.y());
01173               item->Clip = FlattenPath(item->PoLine, item->Segments);
01174               m_Doc->AdjustItemSize(item);
01175        }
01176        item->OwnPage = m_Doc->OnPage(item);
01177        //ite->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
01178        item->setTextFlowMode(PageItem::TextFlowDisabled);
01179        if (oostyle.haveGradient)
01180        {
01181               item->GrType = 0;
01182               if (oostyle.gradient.Stops() > 1)
01183               {
01184                      item->fill_gradient = oostyle.gradient;
01185                      if (oostyle.gradientType == 1)
01186                      {
01187                             bool flipped = false;
01188                             double gradientAngle(oostyle.gradientAngle);
01189                             if ((gradientAngle == 0) || (gradientAngle == 180) || (gradientAngle == 90) || (gradientAngle == 270))
01190                             {
01191                                    if ((gradientAngle == 0) || (gradientAngle == 180))
01192                                    {
01193                                           item->GrType = 2;
01194                                           item->GrStartX = item->width() / 2.0;
01195                                           item->GrStartY = 0;
01196                                           item->GrEndX = item->width() / 2.0;
01197                                           item->GrEndY = item->height();
01198                                    }
01199                                    else if ((gradientAngle == 90) || (gradientAngle == 270))
01200                                    {
01201                                           item->GrType = 1;
01202                                           item->GrStartX = 0;
01203                                           item->GrStartY = item->height() / 2.0;
01204                                           item->GrEndX = item->width();
01205                                           item->GrEndY = item->height() / 2.0;
01206                                    }
01207                             }
01208                             else
01209                             {
01210                                    if ((gradientAngle > 90) && (gradientAngle < 270))
01211                                           gradientAngle -= 180;
01212                                    else if ((gradientAngle > 270) && (gradientAngle < 360))
01213                                    {
01214                                           gradientAngle = 360 - gradientAngle;
01215                                           flipped = true;
01216                                    }
01217                                    double xpos;
01218                                    xpos = (item->width() / 2) * tan(gradientAngle* M_PI / 180.0) * (item->height() / item->width()) + (item->width() / 2);
01219                                    if ((xpos < 0) || (xpos > item->width()))
01220                                    {
01221                                           xpos = (item->height() / 2)- (item->height() / 2) * tan(gradientAngle* M_PI / 180.0) * (item->height() / item->width());
01222                                           if (flipped)
01223                                           {
01224                                                  item->GrEndX = item->width();
01225                                                  item->GrEndY = item->height() - xpos;
01226                                                  item->GrStartX = 0;
01227                                                  item->GrStartY = xpos;
01228                                           }
01229                                           else
01230                                           {
01231                                                  item->GrEndY = xpos;
01232                                                  item->GrEndX = item->width();
01233                                                  item->GrStartX = 0;
01234                                                  item->GrStartY = item->height() - xpos;
01235                                           }
01236                                    }
01237                                    else
01238                                    {
01239                                           item->GrEndX = xpos;
01240                                           item->GrEndY = item->height();
01241                                           item->GrStartX = item->width() - xpos;
01242                                           item->GrStartY = 0;
01243                                    }
01244                                    if (flipped)
01245                                    {
01246                                           item->GrEndX = item->width() - xpos;
01247                                           item->GrEndY = item->height();
01248                                           item->GrStartX = xpos;
01249                                           item->GrStartY = 0;
01250                                    }
01251                                    item->GrType = 6;
01252                             }
01253                      }
01254                      if (oostyle.gradientType == 2)
01255                      {
01256                             item->GrType = 7;
01257                             item->GrStartX = item->width() * oostyle.gradientPointX;
01258                             item->GrStartY = item->height()* oostyle.gradientPointY;
01259                             if (item->width() >= item->height())
01260                             {
01261                                    item->GrEndX = item->width();
01262                                    item->GrEndY = item->height() / 2.0;
01263                             }
01264                             else
01265                             {
01266                                    item->GrEndX = item->width() / 2.0;
01267                                    item->GrEndY = item->height();
01268                             }
01269                             //m_Doc->view()->updateGradientVectors(ite);
01270                             item->updateGradientVectors();
01271                      }
01272               }
01273               else
01274               {
01275                      QPtrVector<VColorStop> cstops = oostyle.gradient.colorStops();
01276                      item->setFillColor(cstops.at(0)->name);
01277                      item->setFillShade(cstops.at(0)->shade);
01278               }
01279        }
01280        return item;
01281 }
01282 
01283 void OODPlug::createStyleMap( QDomDocument &docstyles )
01284 {
01285        QDomElement styles = docstyles.documentElement();
01286        if( styles.isNull() )
01287               return;
01288 
01289        QDomNode fixedStyles = styles.namedItem( "office:styles" );
01290        if( !fixedStyles.isNull() )
01291        {
01292               insertDraws( fixedStyles.toElement() );
01293               insertStyles( fixedStyles.toElement() );
01294        }
01295        QDomNode automaticStyles = styles.namedItem( "office:automatic-styles" );
01296        if( !automaticStyles.isNull() )
01297               insertStyles( automaticStyles.toElement() );
01298 
01299        QDomNode masterStyles = styles.namedItem( "office:master-styles" );
01300        if( !masterStyles.isNull() )
01301               insertStyles( masterStyles.toElement() );
01302 }
01303 
01304 void OODPlug::insertDraws( const QDomElement& styles )
01305 {
01306        for( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
01307        {
01308               QDomElement e = n.toElement();
01309               if( !e.hasAttribute( "draw:name" ) )
01310                      continue;
01311               QString name = e.attribute( "draw:name" );
01312               m_draws.insert( name, new QDomElement( e ) );
01313        }
01314 }
01315 
01316 void OODPlug::insertStyles( const QDomElement& styles )
01317 {
01318        for ( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
01319        {
01320               QDomElement e = n.toElement();
01321               if( !e.hasAttribute( "style:name" ) )
01322                      continue;
01323               QString name = e.attribute( "style:name" );
01324               m_styles.insert( name, new QDomElement( e ) );
01325        }
01326 }
01327 
01328 void OODPlug::fillStyleStack( const QDomElement& object )
01329 {
01330        if( object.hasAttribute( "presentation:style-name" ) )
01331               addStyles( m_styles[object.attribute( "presentation:style-name" )] );
01332        if( object.hasAttribute( "draw:style-name" ) )
01333               addStyles( m_styles[object.attribute( "draw:style-name" )] );
01334        if( object.hasAttribute( "draw:text-style-name" ) )
01335               addStyles( m_styles[object.attribute( "draw:text-style-name" )] );
01336        if( object.hasAttribute( "text:style-name" ) )
01337               addStyles( m_styles[object.attribute( "text:style-name" )] );
01338 }
01339 
01340 void OODPlug::addStyles( const QDomElement* style )
01341 {
01342        if( style->hasAttribute( "style:parent-style-name" ) )
01343               addStyles( m_styles[style->attribute( "style:parent-style-name" )] );
01344        m_styleStack.push( *style );
01345 }
01346 
01347 void OODPlug::storeObjectStyles( const QDomElement& object )
01348 {
01349        fillStyleStack( object );
01350 }
01351 
01352 double OODPlug::parseUnit(const QString &unit)
01353 {
01354        QString unitval=unit;
01355        if (unit.isEmpty())
01356               return 0.0;
01357        if( unit.right( 2 ) == "pt" )
01358               unitval.replace( "pt", "" );
01359        else if( unit.right( 2 ) == "cm" )
01360               unitval.replace( "cm", "" );
01361        else if( unit.right( 2 ) == "mm" )
01362               unitval.replace( "mm" , "" );
01363        else if( unit.right( 2 ) == "in" )
01364               unitval.replace( "in", "" );
01365        else if( unit.right( 2 ) == "px" )
01366               unitval.replace( "px", "" );
01367        double value = unitval.toDouble();
01368        if( unit.right( 2 ) == "pt" )
01369               value = value;
01370        else if( unit.right( 2 ) == "cm" )
01371               value = ( value / 2.54 ) * 72;
01372        else if( unit.right( 2 ) == "mm" )
01373               value = ( value / 25.4 ) * 72;
01374        else if( unit.right( 2 ) == "in" )
01375               value = value * 72;
01376        else if( unit.right( 2 ) == "px" )
01377               value = value;
01378        return value;
01379 }
01380 
01381 QColor OODPlug::parseColorN( const QString &rgbColor )
01382 {
01383        int r, g, b;
01384        keywordToRGB( rgbColor, r, g, b );
01385        return QColor( r, g, b );
01386 }
01387 
01388 QString OODPlug::parseColor( const QString &s )
01389 {
01390        QColor c;
01391        QString ret = CommonStrings::None;
01392        if( s.startsWith( "rgb(" ) )
01393        {
01394               QString parse = s.stripWhiteSpace();
01395               QStringList colors = QStringList::split( ',', parse );
01396               QString r = colors[0].right( ( colors[0].length() - 4 ) );
01397               QString g = colors[1];
01398               QString b = colors[2].left( ( colors[2].length() - 1 ) );
01399               if( r.contains( "%" ) )
01400               {
01401                      r = r.left( r.length() - 1 );
01402                      r = QString::number( static_cast<int>( ( static_cast<double>( 255 * r.toDouble() ) / 100.0 ) ) );
01403               }
01404               if( g.contains( "%" ) )
01405               {
01406                      g = g.left( g.length() - 1 );
01407                      g = QString::number( static_cast<int>( ( static_cast<double>( 255 * g.toDouble() ) / 100.0 ) ) );
01408               }
01409               if( b.contains( "%" ) )
01410               {
01411                      b = b.left( b.length() - 1 );
01412                      b = QString::number( static_cast<int>( ( static_cast<double>( 255 * b.toDouble() ) / 100.0 ) ) );
01413               }
01414               c = QColor(r.toInt(), g.toInt(), b.toInt());
01415        }
01416        else
01417        {
01418               QString rgbColor = s.stripWhiteSpace();
01419               if( rgbColor.startsWith( "#" ) )
01420                      c.setNamedColor( rgbColor );
01421               else
01422                      c = parseColorN( rgbColor );
01423        }
01424        ColorList::Iterator it;
01425        bool found = false;
01426        int r, g, b;
01427        QColor tmpR;
01428        for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
01429        {
01430               if (it.data().getColorModel() == colorModelRGB)
01431               {
01432                      it.data().getRGB(&r, &g, &b);
01433                      tmpR.setRgb(r, g, b);
01434                      if (c == tmpR)
01435                      {
01436                             ret = it.key();
01437                             found = true;
01438                      }
01439               }
01440        }
01441        if (!found)
01442        {
01443               ScColor tmp;
01444               tmp.fromQColor(c);
01445               tmp.setSpotColor(false);
01446               tmp.setRegistrationColor(false);
01447               m_Doc->PageColors.insert("FromOODraw"+c.name(), tmp);
01448               importedColors.append("FromOODraw"+c.name());
01449               ret = "FromOODraw"+c.name();
01450        }
01451        return ret;
01452 }
01453 
01454 void OODPlug::parseTransform(FPointArray *composite, const QString &transform)
01455 {
01456        double dx, dy;
01457        QWMatrix result;
01458        QStringList subtransforms = QStringList::split(')', transform);
01459        QStringList::ConstIterator it = subtransforms.begin();
01460        QStringList::ConstIterator end = subtransforms.end();
01461        for (; it != end; ++it)
01462        {
01463               QStringList subtransform = QStringList::split('(', (*it));
01464               subtransform[0] = subtransform[0].stripWhiteSpace().lower();
01465               subtransform[1] = subtransform[1].simplifyWhiteSpace();
01466               QRegExp reg("[,( ]");
01467               QStringList params = QStringList::split(reg, subtransform[1]);
01468               if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
01469                      subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
01470               if(subtransform[0] == "rotate")
01471               {
01472                      result = QWMatrix();
01473                      result.rotate(-parseUnit(params[0]) * 180 / M_PI);
01474                      composite->map(result);
01475               }
01476               else if(subtransform[0] == "translate")
01477               {
01478                      if(params.count() == 2)
01479                      {
01480                             dx = parseUnit(params[0]);
01481                             dy = parseUnit(params[1]);
01482                      }
01483                      else
01484                      {
01485                             dx = parseUnit(params[0]);
01486                             dy =0.0;
01487                      }
01488                      result = QWMatrix();
01489                      result.translate(dx, dy);
01490                      composite->map(result);
01491               }
01492               else if(subtransform[0] == "skewx")
01493               {
01494                      result = QWMatrix();
01495                      result.shear(-tan(params[0].toDouble()), 0.0);
01496                      composite->map(result);
01497               }
01498               else if(subtransform[0] == "skewy")
01499               {
01500                      result = QWMatrix();
01501                      result.shear(0.0, -tan(params[0].toDouble()));
01502                      composite->map(result);
01503               }
01504        }
01505 }
01506 
01507 void OODPlug::parseViewBox( const QDomElement& object, double *x, double *y, double *w, double *h )
01508 {
01509        if( !object.attribute( "svg:viewBox" ).isEmpty() )
01510        {
01511               QString viewbox( object.attribute( "svg:viewBox" ) );
01512               QStringList points = QStringList::split( ' ', viewbox.replace( QRegExp(","), " ").simplifyWhiteSpace() );
01513               *x = points[0].toDouble();
01514               *y = points[1].toDouble();
01515               *w = points[2].toDouble();
01516               *h = points[3].toDouble();
01517        }
01518 }
01519 
01520 void OODPlug::appendPoints(FPointArray *composite, const QDomElement& object)
01521 {
01522        double x = parseUnit(object.attribute("svg:x"));
01523        double y = parseUnit(object.attribute("svg:y")) ;
01524        double w = parseUnit(object.attribute("svg:width"));
01525        double h = parseUnit(object.attribute("svg:height"));
01526        double vx = 0;
01527        double vy = 0;
01528        double vw = 1;
01529        double vh = 1;
01530        parseViewBox(object, &vx, &vy, &vw, &vh);
01531        QStringList ptList = QStringList::split( ' ', object.attribute( "draw:points" ) );
01532        FPoint point, firstP;
01533        bool bFirst = true;
01534        for( QStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it )
01535        {
01536               point = FPoint((*it).section( ',', 0, 0 ).toDouble(), (*it).section( ',', 1, 1 ).toDouble());
01537               if (bFirst)
01538               {
01539                      composite->addPoint(point);
01540                      composite->addPoint(point);
01541                      firstP = point;
01542                      bFirst = false;
01543               }
01544               else
01545               {
01546                      composite->addPoint(point);
01547                      composite->addPoint(point);
01548                      composite->addPoint(point);
01549                      composite->addPoint(point);
01550               }
01551     }
01552        composite->addPoint(firstP);
01553        composite->addPoint(firstP);
01554        QWMatrix mat;
01555        mat.translate(x, y);
01556        mat.scale(w / vw, h / vh);
01557        composite->map(mat);
01558 }
01559 
01560 const char * OODPlug::getCoord( const char *ptr, double &number )
01561 {
01562        int integer, exponent;
01563        double decimal, frac;
01564        int sign, expsign;
01565 
01566        exponent = 0;
01567        integer = 0;
01568        frac = 1.0;
01569        decimal = 0;
01570        sign = 1;
01571        expsign = 1;
01572 
01573        // read the sign
01574        if(*ptr == '+')
01575               ptr++;
01576        else if(*ptr == '-')
01577        {
01578               ptr++;
01579               sign = -1;
01580        }
01581 
01582        // read the integer part
01583        while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
01584               integer = (integer * 10) + *(ptr++) - '0';
01585        if(*ptr == '.') // read the decimals
01586        {
01587               ptr++;
01588               while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
01589                      decimal += (*(ptr++) - '0') * (frac *= 0.1);
01590        }
01591 
01592        if(*ptr == 'e' || *ptr == 'E') // read the exponent part
01593        {
01594               ptr++;
01595 
01596               // read the sign of the exponent
01597               if(*ptr == '+')
01598                      ptr++;
01599               else if(*ptr == '-')
01600               {
01601                      ptr++;
01602                      expsign = -1;
01603               }
01604 
01605               exponent = 0;
01606               while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
01607               {
01608                      exponent *= 10;
01609                      exponent += *ptr - '0';
01610                      ptr++;
01611               }
01612        }
01613        number = integer + decimal;
01614        number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
01615 
01616        // skip the following space
01617        if(*ptr == ' ')
01618               ptr++;
01619 
01620        return ptr;
01621 }
01622 
01623 bool OODPlug::parseSVG( const QString &s, FPointArray *ite )
01624 {
01625        QString d = s;
01626        d = d.replace( QRegExp( "," ), " ");
01627        bool ret = false;
01628        if( !d.isEmpty() )
01629        {
01630               d = d.simplifyWhiteSpace();
01631               const char *ptr = d.latin1();
01632               const char *end = d.latin1() + d.length() + 1;
01633               double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
01634               double px1, py1, px2, py2, px3, py3;
01635               bool relative;
01636               FirstM = true;
01637               char command = *(ptr++), lastCommand = ' ';
01638               subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
01639               while( ptr < end )
01640               {
01641                      if( *ptr == ' ' )
01642                             ptr++;
01643                      relative = false;
01644                      switch( command )
01645                      {
01646                      case 'm':
01647                             relative = true;
01648                      case 'M':
01649                             {
01650                                    ptr = getCoord( ptr, tox );
01651                                    ptr = getCoord( ptr, toy );
01652                                    WasM = true;
01653                                    subpathx = curx = relative ? curx + tox : tox;
01654                                    subpathy = cury = relative ? cury + toy : toy;
01655                                    svgMoveTo(curx, cury );
01656                                    break;
01657                             }
01658                      case 'l':
01659                             relative = true;
01660                      case 'L':
01661                             {
01662                                    ptr = getCoord( ptr, tox );
01663                                    ptr = getCoord( ptr, toy );
01664                                    curx = relative ? curx + tox : tox;
01665                                    cury = relative ? cury + toy : toy;
01666                                    svgLineTo(ite, curx, cury );
01667                                    break;
01668                             }
01669                      case 'h':
01670                             {
01671                                    ptr = getCoord( ptr, tox );
01672                                    curx = curx + tox;
01673                                    svgLineTo(ite, curx, cury );
01674                                    break;
01675                             }
01676                      case 'H':
01677                             {
01678                                    ptr = getCoord( ptr, tox );
01679                                    curx = tox;
01680                                    svgLineTo(ite, curx, cury );
01681                                    break;
01682                             }
01683                      case 'v':
01684                             {
01685                                    ptr = getCoord( ptr, toy );
01686                                    cury = cury + toy;
01687                                    svgLineTo(ite, curx, cury );
01688                                    break;
01689                             }
01690                      case 'V':
01691                             {
01692                                    ptr = getCoord( ptr, toy );
01693                                    cury = toy;
01694                                    svgLineTo(ite,  curx, cury );
01695                                    break;
01696                             }
01697                      case 'z':
01698                      case 'Z':
01699                             {
01700 //                                 curx = subpathx;
01701 //                                 cury = subpathy;
01702                                    svgClosePath(ite);
01703                                    break;
01704                             }
01705                      case 'c':
01706                             relative = true;
01707                      case 'C':
01708                             {
01709                                    ptr = getCoord( ptr, x1 );
01710                                    ptr = getCoord( ptr, y1 );
01711                                    ptr = getCoord( ptr, x2 );
01712                                    ptr = getCoord( ptr, y2 );
01713                                    ptr = getCoord( ptr, tox );
01714                                    ptr = getCoord( ptr, toy );
01715                                    px1 = relative ? curx + x1 : x1;
01716                                    py1 = relative ? cury + y1 : y1;
01717                                    px2 = relative ? curx + x2 : x2;
01718                                    py2 = relative ? cury + y2 : y2;
01719                                    px3 = relative ? curx + tox : tox;
01720                                    py3 = relative ? cury + toy : toy;
01721                                    svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
01722                                    contrlx = relative ? curx + x2 : x2;
01723                                    contrly = relative ? cury + y2 : y2;
01724                                    curx = relative ? curx + tox : tox;
01725                                    cury = relative ? cury + toy : toy;
01726                                    break;
01727                             }
01728                      case 's':
01729                             relative = true;
01730                      case 'S':
01731                             {
01732                                    ptr = getCoord( ptr, x2 );
01733                                    ptr = getCoord( ptr, y2 );
01734                                    ptr = getCoord( ptr, tox );
01735                                    ptr = getCoord( ptr, toy );
01736                                    px1 = 2 * curx - contrlx;
01737                                    py1 = 2 * cury - contrly;
01738                                    px2 = relative ? curx + x2 : x2;
01739                                    py2 = relative ? cury + y2 : y2;
01740                                    px3 = relative ? curx + tox : tox;
01741                                    py3 = relative ? cury + toy : toy;
01742                                    svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
01743                                    contrlx = relative ? curx + x2 : x2;
01744                                    contrly = relative ? cury + y2 : y2;
01745                                    curx = relative ? curx + tox : tox;
01746                                    cury = relative ? cury + toy : toy;
01747                                    break;
01748                             }
01749                      case 'q':
01750                             relative = true;
01751                      case 'Q':
01752                             {
01753                                    ptr = getCoord( ptr, x1 );
01754                                    ptr = getCoord( ptr, y1 );
01755                                    ptr = getCoord( ptr, tox );
01756                                    ptr = getCoord( ptr, toy );
01757                                    px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
01758                                    py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
01759                                    px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
01760                                    py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
01761                                    px3 = relative ? curx + tox : tox;
01762                                    py3 = relative ? cury + toy : toy;
01763                                    svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
01764                                    contrlx = relative ? curx + x1 : (tox + 2 * x1) * (1.0 / 3.0);
01765                                    contrly = relative ? cury + y1 : (toy + 2 * y1) * (1.0 / 3.0);
01766                                    curx = relative ? curx + tox : tox;
01767                                    cury = relative ? cury + toy : toy;
01768                                    break;
01769                             }
01770                      case 't':
01771                             relative = true;
01772                      case 'T':
01773                             {
01774                                    ptr = getCoord(ptr, tox);
01775                                    ptr = getCoord(ptr, toy);
01776                                    xc = 2 * curx - contrlx;
01777                                    yc = 2 * cury - contrly;
01778                                    px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
01779                                    py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
01780                                    px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
01781                                    py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
01782                                    px3 = relative ? curx + tox : tox;
01783                                    py3 = relative ? cury + toy : toy;
01784                                    svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
01785                                    contrlx = xc;
01786                                    contrly = yc;
01787                                    curx = relative ? curx + tox : tox;
01788                                    cury = relative ? cury + toy : toy;
01789                                    break;
01790                             }
01791                      case 'a':
01792                             relative = true;
01793                      case 'A':
01794                             {
01795                                    bool largeArc, sweep;
01796                                    double angle, rx, ry;
01797                                    ptr = getCoord( ptr, rx );
01798                                    ptr = getCoord( ptr, ry );
01799                                    ptr = getCoord( ptr, angle );
01800                                    ptr = getCoord( ptr, tox );
01801                                    largeArc = tox == 1;
01802                                    ptr = getCoord( ptr, tox );
01803                                    sweep = tox == 1;
01804                                    ptr = getCoord( ptr, tox );
01805                                    ptr = getCoord( ptr, toy );
01806                                    calculateArc(ite, relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep );
01807                             }
01808                      }
01809                      lastCommand = command;
01810                      if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
01811                      {
01812                             // there are still coords in this command
01813                             if(command == 'M')
01814                                    command = 'L';
01815                             else if(command == 'm')
01816                                    command = 'l';
01817                      }
01818                      else
01819                             command = *(ptr++);
01820 
01821                      if( lastCommand != 'C' && lastCommand != 'c' &&
01822                              lastCommand != 'S' && lastCommand != 's' &&
01823                              lastCommand != 'Q' && lastCommand != 'q' &&
01824                              lastCommand != 'T' && lastCommand != 't')
01825                      {
01826                             contrlx = curx;
01827                             contrly = cury;
01828                      }
01829               }
01830               if ((lastCommand != 'z') && (lastCommand != 'Z'))
01831                      ret = true;
01832               if (ite->size() > 2)
01833               {
01834                      if ((ite->point(0).x() == ite->point(ite->size()-2).x()) && (ite->point(0).y() == ite->point(ite->size()-2).y()))
01835                             ret = false;
01836               }
01837        }
01838        return ret;
01839 }
01840 
01841 void OODPlug::calculateArc(FPointArray *ite, bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
01842 {
01843        double sin_th, cos_th;
01844        double a00, a01, a10, a11;
01845        double x0, y0, x1, y1, xc, yc;
01846        double d, sfactor, sfactor_sq;
01847        double th0, th1, th_arc;
01848        int i, n_segs;
01849        sin_th = sin(angle * (M_PI / 180.0));
01850        cos_th = cos(angle * (M_PI / 180.0));
01851        double dx;
01852        if(!relative)
01853               dx = (curx - x) / 2.0;
01854        else
01855               dx = -x / 2.0;
01856        double dy;
01857        if(!relative)
01858               dy = (cury - y) / 2.0;
01859        else
01860               dy = -y / 2.0;
01861        double _x1 =  cos_th * dx + sin_th * dy;
01862        double _y1 = -sin_th * dx + cos_th * dy;
01863        double Pr1 = r1 * r1;
01864        double Pr2 = r2 * r2;
01865        double Px = _x1 * _x1;
01866        double Py = _y1 * _y1;
01867        double check = Px / Pr1 + Py / Pr2;
01868        if(check > 1)
01869        {
01870               r1 = r1 * sqrt(check);
01871               r2 = r2 * sqrt(check);
01872        }
01873        a00 = cos_th / r1;
01874        a01 = sin_th / r1;
01875        a10 = -sin_th / r2;
01876        a11 = cos_th / r2;
01877        x0 = a00 * curx + a01 * cury;
01878        y0 = a10 * curx + a11 * cury;
01879        if(!relative)
01880               x1 = a00 * x + a01 * y;
01881        else
01882               x1 = a00 * (curx + x) + a01 * (cury + y);
01883        if(!relative)
01884               y1 = a10 * x + a11 * y;
01885        else
01886               y1 = a10 * (curx + x) + a11 * (cury + y);
01887        d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
01888        sfactor_sq = 1.0 / d - 0.25;
01889        if(sfactor_sq < 0)
01890               sfactor_sq = 0;
01891        sfactor = sqrt(sfactor_sq);
01892        if(sweepFlag == largeArcFlag)
01893               sfactor = -sfactor;
01894        xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
01895        yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
01896 
01897        th0 = atan2(y0 - yc, x0 - xc);
01898        th1 = atan2(y1 - yc, x1 - xc);
01899        th_arc = th1 - th0;
01900        if(th_arc < 0 && sweepFlag)
01901               th_arc += 2 * M_PI;
01902        else if(th_arc > 0 && !sweepFlag)
01903               th_arc -= 2 * M_PI;
01904        n_segs = static_cast<int>(ceil(fabs(th_arc / (M_PI * 0.5 + 0.001))));
01905        for(i = 0; i < n_segs; i++)
01906        {
01907               {
01908                      double sin_th, cos_th;
01909                      double a00, a01, a10, a11;
01910                      double x1, y1, x2, y2, x3, y3;
01911                      double t;
01912                      double th_half;
01913                      double _th0 = th0 + i * th_arc / n_segs;
01914                      double _th1 = th0 + (i + 1) * th_arc / n_segs;
01915                      sin_th = sin(angle * (M_PI / 180.0));
01916                      cos_th = cos(angle * (M_PI / 180.0));
01917                      a00 = cos_th * r1;
01918                      a01 = -sin_th * r2;
01919                      a10 = sin_th * r1;
01920                      a11 = cos_th * r2;
01921                      th_half = 0.5 * (_th1 - _th0);
01922                      t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
01923                      x1 = xc + cos(_th0) - t * sin(_th0);
01924                      y1 = yc + sin(_th0) + t * cos(_th0);
01925                      x3 = xc + cos(_th1);
01926                      y3 = yc + sin(_th1);
01927                      x2 = x3 + t * sin(_th1);
01928                      y2 = y3 - t * cos(_th1);
01929                      svgCurveToCubic(ite, a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 );
01930               }
01931        }
01932        if(!relative)
01933               curx = x;
01934        else
01935               curx += x;
01936        if(!relative)
01937               cury = y;
01938        else
01939               cury += y;
01940 }
01941 
01942 void OODPlug::svgMoveTo(double x1, double y1)
01943 {
01944        CurrX = x1;
01945        CurrY = y1;
01946        StartX = x1;
01947        StartY = y1;
01948        PathLen = 0;
01949 }
01950 
01951 void OODPlug::svgLineTo(FPointArray *i, double x1, double y1)
01952 {
01953        if ((!FirstM) && (WasM))
01954        {
01955               i->setMarker();
01956               PathLen += 4;
01957        }
01958        FirstM = false;
01959        WasM = false;
01960        if (i->size() > 3)
01961        {
01962               FPoint b1 = i->point(i->size()-4);
01963               FPoint b2 = i->point(i->size()-3);
01964               FPoint b3 = i->point(i->size()-2);
01965               FPoint b4 = i->point(i->size()-1);
01966               FPoint n1 = FPoint(CurrX, CurrY);
01967               FPoint n2 = FPoint(x1, y1);
01968               if ((b1 == n1) && (b2 == n1) && (b3 == n2) && (b4 == n2))
01969                      return;
01970        }
01971        i->addPoint(FPoint(CurrX, CurrY));
01972        i->addPoint(FPoint(CurrX, CurrY));
01973        i->addPoint(FPoint(x1, y1));
01974        i->addPoint(FPoint(x1, y1));
01975        CurrX = x1;
01976        CurrY = y1;
01977        PathLen += 4;
01978 }
01979 
01980 void OODPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3)
01981 {
01982        if ((!FirstM) && (WasM))
01983        {
01984               i->setMarker();
01985               PathLen += 4;
01986        }
01987        FirstM = false;
01988        WasM = false;
01989        if (PathLen > 3)
01990        {
01991               FPoint b1 = i->point(i->size()-4);
01992               FPoint b2 = i->point(i->size()-3);
01993               FPoint b3 = i->point(i->size()-2);
01994               FPoint b4 = i->point(i->size()-1);
01995               FPoint n1 = FPoint(CurrX, CurrY);
01996               FPoint n2 = FPoint(x1, y1);
01997               FPoint n3 = FPoint(x3, y3);
01998               FPoint n4 = FPoint(x2, y2);
01999               if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4))
02000                      return;
02001        }
02002        i->addPoint(FPoint(CurrX, CurrY));
02003        i->addPoint(FPoint(x1, y1));
02004        i->addPoint(FPoint(x3, y3));
02005        i->addPoint(FPoint(x2, y2));
02006        CurrX = x3;
02007        CurrY = y3;
02008        PathLen += 4;
02009 }
02010 
02011 void OODPlug::svgClosePath(FPointArray *i)
02012 {
02013        if (PathLen > 2)
02014        {
02015               if ((PathLen == 4) || (i->point(i->size()-2).x() != StartX) || (i->point(i->size()-2).y() != StartY))
02016               {
02017                      i->addPoint(i->point(i->size()-2));
02018                      i->addPoint(i->point(i->size()-3));
02019                      i->addPoint(FPoint(StartX, StartY));
02020                      i->addPoint(FPoint(StartX, StartY));
02021               }
02022        }
02023 }
02024 
02025 OODPlug::~OODPlug()
02026 {
02027        delete tmpSel;
02028 }
02029