Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

svgexplugin.cpp

Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008                           svgexplugin.cpp  -  description
00009                              -------------------
00010     begin                : Sun Aug 3 08:00:00 CEST 2002
00011     copyright            : (C) 2002 by Franz Schmid
00012     email                : Franz.Schmid@altmuehlnet.de
00013  ***************************************************************************/
00014 
00015 /***************************************************************************
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 #include <QFile>
00025 #include <QTextStream>
00026 #include <QDataStream>
00027 #include <QByteArray>
00028 #include <QList>
00029 
00030 #include "svgexplugin.h"
00031 
00032 #include "scconfig.h"
00033 #include "canvas.h"
00034 #include "cmsettings.h"
00035 #include "commonstrings.h"
00036 #include "customfdialog.h"
00037 #include "scribuscore.h"
00038 #include "page.h"
00039 #include "scgzfile.h"
00040 #include "prefsmanager.h"
00041 #include "prefsfile.h"
00042 #include "prefscontext.h"
00043 #include "scmessagebox.h"
00044 #include "util.h"
00045 #include "customfdialog.h"
00046 #include "sctextstruct.h"
00047 #include "guidemanager.h"
00048 #include "sccolorengine.h"
00049 #include "util_formats.h"
00050 
00051 int svgexplugin_getPluginAPIVersion()
00052 {
00053     return PLUGIN_API_VERSION;
00054 }
00055 
00056 ScPlugin* svgexplugin_getPlugin()
00057 {
00058     SVGExportPlugin* plug = new SVGExportPlugin();
00059     Q_CHECK_PTR(plug);
00060     return plug;
00061 }
00062 
00063 void svgexplugin_freePlugin(ScPlugin* plugin)
00064 {
00065     SVGExportPlugin* plug = dynamic_cast<SVGExportPlugin*>(plugin);
00066     Q_ASSERT(plug);
00067     delete plug;
00068 }
00069 
00070 SVGExportPlugin::SVGExportPlugin() : ScActionPlugin()
00071 {
00072     // Set action info in languageChange, so we only have to do
00073     // it in one place.
00074     languageChange();
00075 }
00076 
00077 SVGExportPlugin::~SVGExportPlugin() {};
00078 
00079 void SVGExportPlugin::languageChange()
00080 {
00081     // Note that we leave the unused members unset. They'll be initialised
00082     // with their default ctors during construction.
00083     // Action name
00084     m_actionInfo.name = "ExportAsSVG";
00085     // Action text for menu, including accel
00086     m_actionInfo.text = tr("Save as &SVG...");
00087     // Menu
00088     m_actionInfo.menu = "FileExport";
00089     m_actionInfo.enabledOnStartup = true;
00090     m_actionInfo.needsNumObjects = -1;
00091 }
00092 
00093 const QString SVGExportPlugin::fullTrName() const
00094 {
00095     return QObject::tr("SVG Export");
00096 }
00097 
00098 const ScActionPlugin::AboutData* SVGExportPlugin::getAboutData() const
00099 {
00100     AboutData* about = new AboutData;
00101     about->authors = "Franz Schmid <franz@scribus.info>";
00102     about->shortDescription = tr("Exports SVG Files");
00103     about->description = tr("Exports the current page into an SVG file.");
00104     about->license = "GPL";
00105     Q_CHECK_PTR(about);
00106     return about;
00107 }
00108 
00109 void SVGExportPlugin::deleteAboutData(const AboutData* about) const
00110 {
00111     Q_ASSERT(about);
00112     delete about;
00113 }
00114 
00115 bool SVGExportPlugin::run(ScribusDoc* doc, QString filename)
00116 {
00117     Q_ASSERT(filename.isEmpty());
00118     QString fileName;
00119     if (doc!=0)
00120     {
00121         PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("svgex");
00122         QString wdir = prefs->get("wdir", ".");
00123         CustomFDialog *openDia = new CustomFDialog(doc->scMW(), wdir, QObject::tr("Save as"), QObject::tr("%1;;All Files (*)").arg(FormatsManager::instance()->extensionsForFormat(FormatsManager::SVG)), fdCompressFile);
00124         openDia->setSelection(getFileNameByPage(doc, doc->currentPage()->pageNr(), "svg"));
00125         openDia->setExtension("svg");
00126         openDia->setZipExtension("svgz");
00127         if (openDia->exec())
00128         {
00129             if (openDia->SaveZip->isChecked())
00130                 openDia->handleCompress();
00131             fileName = openDia->selectedFile();
00132         }
00133         delete openDia;
00134 
00135         if (!fileName.isEmpty())
00136         {
00137             prefs->set("wdir", fileName.left(fileName.lastIndexOf("/")));
00138             QFile f(fileName);
00139             if (f.exists())
00140             {
00141                 int exit = QMessageBox::warning(doc->scMW(), CommonStrings::trWarning,
00142                     QObject::tr("Do you really want to overwrite the file:\n%1 ?").arg(fileName),
00143                     QMessageBox::Yes | QMessageBox::No);
00144                 if (exit == QMessageBox::No)
00145                     return true;
00146             }
00147             SVGExPlug *dia = new SVGExPlug(doc);
00148             dia->doExport(fileName);
00149             delete dia;
00150         }
00151         else
00152             return true;
00153     }
00154     return true;
00155 }
00156 
00157 SVGExPlug::SVGExPlug( ScribusDoc* doc )
00158 {
00159     m_Doc=doc;
00160     m_View=m_Doc->view();
00161     m_ScMW=m_Doc->scMW();
00162 }
00163 
00164 bool SVGExPlug::doExport( QString fName )
00165 {
00166 #ifdef USECAIRO
00167     Page *Seite = m_Doc->currentPage();
00168     int clipx = static_cast<int>(Seite->xOffset());
00169     int clipy = static_cast<int>(Seite->yOffset());
00170     int clipw = qRound(Seite->width());
00171     int cliph = qRound(Seite->height());
00172     double sca = m_View->scale();
00173     double cx = m_Doc->minCanvasCoordinate.x();
00174     double cy = m_Doc->minCanvasCoordinate.y();
00175     m_Doc->minCanvasCoordinate = FPoint(0, 0);
00176     bool frs = m_Doc->guidesSettings.framesShown;
00177     bool ctrls = m_Doc->guidesSettings.showControls;
00178     m_Doc->guidesSettings.framesShown = false;
00179     m_Doc->guidesSettings.showControls = false;
00180     m_View->setScale(1.0);
00181     m_View->m_canvas->setPreviewMode(true);
00182     ScPainter *painter = new ScPainter(fName, clipw, cliph, 1.0, 0);
00183     painter->clear(m_Doc->papColor);
00184     painter->translate(-clipx, -clipy);
00185     painter->setFillMode(ScPainter::Solid);
00186     m_View->m_canvas->DrawMasterItems(painter, Seite, QRect(clipx, clipy, clipw, cliph));
00187     m_View->m_canvas->DrawPageItems(painter, QRect(clipx, clipy, clipw, cliph));
00188     painter->end();
00189     m_Doc->guidesSettings.framesShown = frs;
00190     m_Doc->guidesSettings.showControls = ctrls;
00191     m_View->setScale(sca);
00192     delete painter;
00193     m_View->m_canvas->setPreviewMode(false);
00194     m_Doc->minCanvasCoordinate = FPoint(cx, cy);
00195 #else
00196     QDomDocument docu("svgdoc");
00197     QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
00198     QString st = "<svg></svg>";
00199     docu.setContent(st);
00200     double pageWidth  = m_Doc->pageWidth;
00201     double pageHeight = m_Doc->pageHeight;
00202     QDomElement elem = docu.documentElement();
00203     elem.setAttribute("width", FToStr(m_Doc->pageWidth)+"pt");
00204     elem.setAttribute("height", FToStr(m_Doc->pageHeight)+"pt");
00205     elem.setAttribute("viewBox", QString("0 0 %1 %2").arg(pageWidth).arg(pageHeight));
00206     elem.setAttribute("xmlns", "http://www.w3.org/2000/svg");
00207     elem.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");
00208     Page *Seite;
00209     GradCount = 0;
00210     ClipCount = 0;
00211     Seite = m_Doc->MasterPages.at(m_Doc->MasterNames[m_Doc->currentPage()->MPageNam]);
00212     ProcessPage(Seite, &docu, &elem);
00213     Seite = m_Doc->currentPage();
00214     ProcessPage(Seite, &docu, &elem);
00215     if(fName.right(2) == "gz")
00216     {
00217         // zipped saving
00218         ScGzFile gzf(fName, docu.toString().toUtf8());
00219         if (!gzf.write(vo.toUtf8().data()))
00220             return false;
00221     }
00222     else
00223     {
00224         QFile f(fName);
00225         if(!f.open(QIODevice::WriteOnly))
00226             return false;
00227         QDataStream s(&f);
00228         QString wr = vo;
00229         wr += docu.toString();
00230         QByteArray utf8wr = wr.toUtf8();
00231         s.writeRawData(utf8wr.data(), utf8wr.length());
00232         f.close();
00233     }
00234 #endif
00235     return true;
00236 }
00237 
00238 #ifndef USECAIRO
00239 void SVGExPlug::ProcessPage(Page *Seite, QDomDocument *docu, QDomElement *elem)
00240 {
00241     QString tmp, trans, fill, stroke, strokeW, strokeLC, strokeLJ, strokeDA, gradi, Clipi, chx;
00242     int d;
00243     ScText *hl;
00244     int Lnr = 0;
00245     ScLayer ll;
00246     ll.isPrintable = false;
00247     ll.LNr = 0;
00248     QDomElement ob, gr, tp, tp2, defi, grad;
00249     QDomText tp1;
00250     PageItem *Item;
00251     gradi = "Grad";
00252     Clipi = "Clip";
00253     QList<PageItem*> Items;
00254     Page* SavedAct = m_Doc->currentPage();
00255     m_Doc->setCurrentPage(Seite);
00256     if (Seite->pageName().isEmpty())
00257         Items = m_Doc->DocItems;
00258     else
00259         Items = m_Doc->MasterItems;
00260     for (int la = 0; la < m_Doc->Layers.count(); la++)
00261     {
00262         m_Doc->Layers.levelToLayer(ll, Lnr);
00263         if (ll.isPrintable)
00264         {
00265             for(int j = 0; j < Items.count(); ++j)
00266             {
00267                 Item = Items.at(j);
00268                 if (Item->LayerNr != ll.LNr)
00269                     continue;
00270                 double x = Seite->xOffset();
00271                 double y = Seite->yOffset();
00272                 double w = Seite->width();
00273                 double h = Seite->height();
00274                 double x2 = Item->BoundingX;
00275                 double y2 = Item->BoundingY;
00276                 double w2 = Item->BoundingW;
00277                 double h2 = Item->BoundingH;
00278                 if (!( qMax( x, x2 ) <= qMin( x+w, x2+w2 ) && qMax( y, y2 ) <= qMin( y+h, y2+h2 )))
00279                     continue;
00280                 if ((Item->fillColor() != CommonStrings::None) || (Item->GrType != 0))
00281                 {
00282                     fill = "fill:"+SetColor(Item->fillColor(), Item->fillShade())+";";
00283                     if (Item->GrType != 0)
00284                     {
00285                         defi = docu->createElement("defs");
00286                         if ((Item->GrType == 5) || (Item->GrType == 7))
00287                             grad = docu->createElement("radialGradient");
00288                         else
00289                             grad = docu->createElement("linearGradient");
00290                         grad.setAttribute("id", gradi+IToStr(GradCount));
00291                         grad.setAttribute("gradientUnits", "userSpaceOnUse");
00292                         switch (Item->GrType)
00293                         {
00294                             case 1:
00295                                 grad.setAttribute("x1", "0");
00296                                 grad.setAttribute("y1", FToStr(Item->height() / 2));
00297                                 grad.setAttribute("x2", FToStr(Item->width()));
00298                                 grad.setAttribute("y2", FToStr(Item->height() / 2));
00299                                 break;
00300                             case 2:
00301                                 grad.setAttribute("x1", FToStr(Item->width()/ 2));
00302                                 grad.setAttribute("y1", "0");
00303                                 grad.setAttribute("x2", FToStr(Item->width()/ 2));
00304                                 grad.setAttribute("y2", FToStr(Item->height()));
00305                                 break;
00306                             case 3:
00307                                 grad.setAttribute("x1", "0");
00308                                 grad.setAttribute("y1", "0");
00309                                 grad.setAttribute("x2", FToStr(Item->width()));
00310                                 grad.setAttribute("y2", FToStr(Item->height()));
00311                                 break;
00312                             case 4:
00313                                 grad.setAttribute("x1", "0");
00314                                 grad.setAttribute("y1", FToStr(Item->height()));
00315                                 grad.setAttribute("x2", FToStr(Item->width()));
00316                                 grad.setAttribute("y2", "0");
00317                                 break;
00318                             case 5:
00319                                 grad.setAttribute("r", FToStr(qMax(Item->width() / 2, Item->height() / 2)));
00320                                 grad.setAttribute("cx", FToStr(Item->width() / 2));
00321                                 grad.setAttribute("cy", FToStr(Item->height() / 2));
00322                                 break;
00323                             case 6:
00324                                 grad.setAttribute("x1", FToStr(Item->GrStartX));
00325                                 grad.setAttribute("y1", FToStr(Item->GrStartY));
00326                                 grad.setAttribute("x2", FToStr(Item->GrEndX));
00327                                 grad.setAttribute("y2", FToStr(Item->GrEndY));
00328                                 break;
00329                             case 7:
00330                                 grad.setAttribute("r", FToStr(qMax(Item->width() / 2, Item->height() / 2)));
00331                                 grad.setAttribute("cx", FToStr(Item->GrStartX));
00332                                 grad.setAttribute("cy", FToStr(Item->GrStartY));
00333                                 break;
00334                         }
00335                         QList<VColorStop*> cstops = Item->fill_gradient.colorStops();
00336                         for (int cst = 0; cst < Item->fill_gradient.Stops(); ++cst)
00337                         {
00338                             QDomElement itcl = docu->createElement("stop");
00339                             itcl.setAttribute("offset", FToStr(cstops.at(cst)->rampPoint*100)+"%");
00340                             itcl.setAttribute("stop-opacity", FToStr(cstops.at(cst)->opacity));
00341                             itcl.setAttribute("stop-color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade));
00342                             grad.appendChild(itcl);
00343                         }
00344                         defi.appendChild(grad);
00345                         fill = "fill:url(#"+gradi+IToStr(GradCount)+");";
00346                         GradCount++;
00347                     }
00348                     if (Item->fillRule)
00349                         fill += " fill-rule:evenodd;";
00350                     else
00351                         fill += " fill-rule:nonzero;";
00352                     if (Item->fillTransparency() != 0)
00353                         fill += " fill-opacity:"+FToStr(1.0 - Item->fillTransparency())+";";
00354                 }
00355                 else
00356                     fill = "fill:none;";
00357                 if (Item->lineColor() != CommonStrings::None)
00358                 {
00359                     stroke = "stroke:"+SetColor(Item->lineColor(), Item->lineShade())+";";
00360                     if (Item->lineTransparency() != 0)
00361                         stroke += " stroke-opacity:"+FToStr(1.0 - Item->lineTransparency())+";";
00362                 }
00363                 else
00364                     stroke = "stroke:none;";
00365                 trans = "translate("+FToStr(Item->xPos()-Seite->xOffset())+", "+FToStr(Item->yPos()-Seite->yOffset())+")";
00366                 if (Item->rotation() != 0)
00367                     trans += " rotate("+FToStr(Item->rotation())+")";
00368                 strokeW = "stroke-width:"+FToStr(Item->lineWidth())+";";
00369                 strokeLC = "stroke-linecap:";
00370                 switch (Item->PLineEnd)
00371                 {
00372                     case Qt::FlatCap:
00373                         strokeLC += "butt;";
00374                         break;
00375                     case Qt::SquareCap:
00376                         strokeLC += "square;";
00377                         break;
00378                     case Qt::RoundCap:
00379                         strokeLC += "round;";
00380                         break;
00381                     default:
00382                         strokeLC += "butt;";
00383                         break;
00384                 }
00385                 strokeLJ = "stroke-linejoin:";
00386                 switch (Item->PLineJoin)
00387                 {
00388                     case Qt::MiterJoin:
00389                         strokeLJ += "miter;";
00390                         break;
00391                     case Qt::BevelJoin:
00392                         strokeLJ += "bevel;";
00393                         break;
00394                     case Qt::RoundJoin:
00395                         strokeLJ += "round;";
00396                         break;
00397                     default:
00398                         strokeLJ += "miter;";
00399                         break;
00400                 }
00401                 strokeDA = "stroke-dasharray:";
00402                 if (Item->DashValues.count() != 0)
00403                 {
00404                     QList<double>::iterator it;
00405                     for ( it = Item->DashValues.begin(); it != Item->DashValues.end(); ++it )
00406                     {
00407                         strokeDA += IToStr(static_cast<int>(*it))+" ";
00408                     }
00409                     strokeDA += "; stroke-dashoffset:"+IToStr(static_cast<int>(Item->DashOffset))+";";
00410                 }
00411                 else
00412                 {
00413                     if (Item->PLineArt == Qt::SolidLine)
00414                         strokeDA += "none;";
00415                     else
00416                     {
00417                         QString Da = getDashString(Item->PLineArt, Item->lineWidth());
00418                         if (Da.isEmpty())
00419                             strokeDA += "none;";
00420                         else
00421                             strokeDA += Da.replace(" ", ", ")+";";
00422                     }
00423                 }
00424                 gr = docu->createElement("g");
00425                 gr.setAttribute("transform", trans);
00426                 if (!Item->asTextFrame())
00427                 {
00428                     if (Item->NamedLStyle.isEmpty())
00429                     {
00430                         if (Item->asPathText())
00431                             gr.setAttribute("style", "fill:none; "+stroke+" "+strokeW+" "+strokeLC+" "+strokeLJ+" "+strokeDA);
00432                         else
00433                             gr.setAttribute("style", fill+" "+stroke+" "+strokeW+" "+strokeLC+" "+strokeLJ+" "+strokeDA);
00434                     }
00435                 }
00436                 switch (Item->itemType())
00437                 {
00438                 case PageItem::Polygon:
00439                     if (Item->NamedLStyle.isEmpty())
00440                     {
00441                         ob = docu->createElement("path");
00442                         ob.setAttribute("d", SetClipPath(Item)+"Z");
00443                     }
00444                     else
00445                     {
00446                         ob = docu->createElement("path");
00447                         ob.setAttribute("d", SetClipPath(Item)+"Z");
00448                         ob.setAttribute("style", fill);
00449                         gr.appendChild(ob);
00450                         multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
00451                         for (int it = ml.size()-1; it > -1; it--)
00452                         {
00453                             if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00454                             {
00455                                 ob = docu->createElement("path");
00456                                 ob.setAttribute("d", SetClipPath(Item)+"Z");
00457                                 ob.setAttribute("style", GetMultiStroke(&ml[it], Item));
00458                                 gr.appendChild(ob);
00459                             }
00460                         }
00461                     }
00462                     break;
00463                 case PageItem::ImageFrame:
00464                     if ((Item->fillColor() != CommonStrings::None) || (Item->GrType != 0))
00465                     {
00466                         ob = docu->createElement("path");
00467                         ob.setAttribute("d", SetClipPath(Item)+"Z");
00468                         ob.setAttribute("style", fill);
00469                         gr.appendChild(ob);
00470                     }
00471                     if ((Item->PicAvail) && (!Item->Pfile.isEmpty()))
00472                     {
00473                         ob = docu->createElement("clipPath");
00474                         ob.setAttribute("id", Clipi+IToStr(ClipCount));
00475                         ob.setAttribute("clipPathUnits", "userSpaceOnUse");
00476                         ob.setAttribute("clip-rule", "evenodd");
00477                         QDomElement cl = docu->createElement("path");
00478                         if (Item->imageClip.size() != 0)
00479                             cl.setAttribute("d", SetClipPathImage(Item)+"Z");
00480                         else
00481                             cl.setAttribute("d", SetClipPath(Item)+"Z");
00482                         ob.appendChild(cl);
00483                         gr.appendChild(ob);
00484                         ScImage img;
00485                         CMSettings cms(m_Doc, Item->IProfile, Item->IRender);
00486                         img.LoadPicture(Item->Pfile, cms, Item->UseEmbedded, true, ScImage::RGBProof, 72);
00487                         img.applyEffect(Item->effectsInUse, m_Doc->PageColors, true);
00488                         QFileInfo fi = QFileInfo(Item->Pfile);
00489                         img.qImage().save(fi.baseName()+".png", "PNG");
00490                         ob = docu->createElement("image");
00491                         ob.setAttribute("clip-path", "url(#"+Clipi+IToStr(ClipCount)+")");
00492                         ob.setAttribute("xlink:href", fi.baseName()+".png");
00493                         ob.setAttribute("x", "0pt");
00494                         ob.setAttribute("y", "0pt");
00495                         ob.setAttribute("width", FToStr(Item->width()));
00496                         ob.setAttribute("height", FToStr(Item->height()));
00497                         ClipCount++;
00498                         gr.appendChild(ob);
00499                     }
00500                     if (Item->NamedLStyle.isEmpty())
00501                     {
00502                         ob = docu->createElement("path");
00503                         ob.setAttribute("d", SetClipPath(Item)+"Z");
00504                         ob.setAttribute("style", "fill:none; "+stroke+" "+strokeW+" "+strokeLC+" "+strokeLJ+" "+strokeDA);
00505                     }
00506                     else
00507                     {
00508                         multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
00509                         for (int it = ml.size()-1; it > -1; it--)
00510                         {
00511                             if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00512                             {
00513                                 ob = docu->createElement("path");
00514                                 ob.setAttribute("d", SetClipPath(Item)+"Z");
00515                                 ob.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item));
00516                                 gr.appendChild(ob);
00517                             }
00518                         }
00519                     }
00520                     break;
00521                 case PageItem::PolyLine:
00522                     if (Item->NamedLStyle.isEmpty())
00523                     {
00524                         ob = docu->createElement("path");
00525                         ob.setAttribute("d", SetClipPath(Item));
00526                     }
00527                     else
00528                     {
00529                         multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
00530                         for (int it = ml.size()-1; it > -1; it--)
00531                         {
00532                             if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00533                             {
00534                                 ob = docu->createElement("path");
00535                                 ob.setAttribute("d", SetClipPath(Item));
00536                                 ob.setAttribute("style", GetMultiStroke(&ml[it], Item));
00537                                 gr.appendChild(ob);
00538                             }
00539                         }
00540                     }
00541                     break;
00542                 case PageItem::TextFrame:
00543                     if ((Item->fillColor() != CommonStrings::None) || (Item->GrType != 0))
00544                     {
00545                         ob = docu->createElement("path");
00546                         ob.setAttribute("d", SetClipPath(Item)+"Z");
00547                         ob.setAttribute("style", fill);
00548                         gr.appendChild(ob);
00549                     }
00550                     ob = docu->createElement("text");
00551                     for (d = 0; d < Item->itemText.length() && ! Item->frameDisplays(d); ++d)
00552                         ;
00553                     for (; d < Item->itemText.length() && Item->frameDisplays(d); ++d)
00554                     {
00555                         hl = Item->itemText.item(d);
00556                         if ((hl->ch == QChar(13)) || (hl->ch == QChar(10)) || (hl->ch == QChar(9)) || (hl->ch == QChar(28)))
00557                             continue;
00558                         if (hl->glyph.yoffset == 0)
00559                             break;
00560                         if (hl->ch == QChar(29))
00561                             chx = " ";
00562                         else
00563                             chx = hl->ch;
00564                         tp = docu->createElement("tspan");
00565                         tp.setAttribute("x", FToStr(hl->glyph.xoffset));
00566                         tp.setAttribute("y", FToStr(hl->glyph.yoffset));
00567                         SetTextProps(&tp, hl);
00568                         tp1 = docu->createTextNode(chx);
00569                         tp.appendChild(tp1);
00570                         ob.appendChild(tp);
00571                     }
00572                     if (Item->NamedLStyle.isEmpty())
00573                     {
00574                         ob = docu->createElement("path");
00575                         ob.setAttribute("d", SetClipPath(Item)+"Z");
00576                         ob.setAttribute("style", "fill:none; "+stroke+" "+strokeW+" "+strokeLC+" "+strokeLJ+" "+strokeDA);
00577                     }
00578                     else
00579                     {
00580                         multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
00581                         for (int it = ml.size()-1; it > -1; it--)
00582                         {
00583                             if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00584                             {
00585                                 ob = docu->createElement("path");
00586                                 ob.setAttribute("d", SetClipPath(Item)+"Z");
00587                                 ob.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item));
00588                                 gr.appendChild(ob);
00589                             }
00590                         }
00591                     }
00592                     break;
00593                 case PageItem::Line:
00594                     if (Item->NamedLStyle.isEmpty())
00595                     {
00596                         ob = docu->createElement("path");
00597                         ob.setAttribute("d", "M 0 0 L "+FToStr(Item->width())+" 0");
00598                     }
00599                     else
00600                     {
00601                         multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
00602                         for (int it = ml.size()-1; it > -1; it--)
00603                         {
00604                             if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00605                             {
00606                                 ob = docu->createElement("path");
00607                                 ob.setAttribute("d", "M 0 0 L "+FToStr(Item->width())+" 0");
00608                                 ob.setAttribute("style", GetMultiStroke(&ml[it], Item));
00609                                 gr.appendChild(ob);
00610                             }
00611                         }
00612                     }
00613                     break;
00614                 case PageItem::PathText:
00615                     if (Item->PoShow)
00616                     {
00617                         if (Item->NamedLStyle.isEmpty())
00618                         {
00619                             ob = docu->createElement("path");
00620                             ob.setAttribute("d", SetClipPath(Item));
00621                             gr.appendChild(ob);
00622                         }
00623                         else
00624                         {
00625                             multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
00626                             for (int it = ml.size()-1; it > -1; it--)
00627                             {
00628                                 if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00629                                 {
00630                                     ob = docu->createElement("path");
00631                                     ob.setAttribute("d", SetClipPath(Item));
00632                                     ob.setAttribute("style", GetMultiStroke(&ml[it], Item));
00633                                     gr.appendChild(ob);
00634                                 }
00635                             }
00636                         }
00637                     }
00638                     ob = docu->createElement("text");
00639                     for (d = 0; d < Item->itemText.length() && !Item->frameDisplays(d); ++d)
00640                         ;
00641                     for (; d < Item->itemText.length() && Item->frameDisplays(d); ++d)
00642                     {
00643                         hl = Item->itemText.item(d);
00644                         if ((hl->ch == QChar(13)) || (hl->ch == QChar(10)) || (hl->ch == QChar(9)) || (hl->ch == QChar(25)) || (hl->ch == QChar(28)))
00645                             continue;
00646                         if (hl->ch == QChar(29))
00647                             chx = " ";
00648                         else
00649                             chx = hl->ch;
00650                         tp = docu->createElement("tspan");
00651                         tp.setAttribute("x", FToStr(hl->PtransX));
00652                         tp.setAttribute("y", FToStr(hl->PtransY));
00653                         tp.setAttribute("rotate", hl->PRot);
00654                         tp2 = docu->createElement("tspan");
00655                         tp2.setAttribute("dx", FToStr(hl->glyph.xoffset));
00656                         tp2.setAttribute("dy", FToStr(hl->glyph.yoffset));
00657                         SetTextProps(&tp2, hl);
00658                         tp1 = docu->createTextNode(chx);
00659                         tp2.appendChild(tp1);
00660                         tp.appendChild(tp2);
00661                         ob.appendChild(tp);
00662                     }
00663                     break;
00664                 default:
00665                     break;
00666                 }
00667                 if (Item->GrType != 0)
00668                     elem->appendChild(defi);
00669                 gr.appendChild(ob);
00670                 elem->appendChild(gr);
00671             }
00672         }
00673         Lnr++;
00674     }
00675     m_Doc->setCurrentPage(SavedAct);
00676 }
00677 
00678 QString SVGExPlug::SetClipPath(PageItem *ite)
00679 {
00680     QString tmp = "";
00681     FPoint np, np1, np2;
00682     bool nPath = true;
00683     if (ite->PoLine.size() > 3)
00684         {
00685         for (uint poi=0; poi<ite->PoLine.size()-3; poi += 4)
00686             {
00687             if (ite->PoLine.point(poi).x() > 900000)
00688                 {
00689                 tmp += "Z ";
00690                 nPath = true;
00691                 continue;
00692                 }
00693             if (nPath)
00694                 {
00695                 np = ite->PoLine.point(poi);
00696                 tmp += "M"+FToStr(np.x())+" "+FToStr(np.y())+" ";
00697                 nPath = false;
00698                 }
00699             np = ite->PoLine.point(poi+1);
00700             tmp += "C"+FToStr(np.x())+" "+FToStr(np.y())+" ";
00701             np1 = ite->PoLine.point(poi+3);
00702             tmp += FToStr(np1.x())+" "+FToStr(np1.y())+" ";
00703             np2 = ite->PoLine.point(poi+2);
00704             tmp += FToStr(np2.x())+" "+FToStr(np2.y())+" ";
00705             }
00706         }
00707     return tmp;
00708 }
00709 
00710 QString SVGExPlug::SetClipPathImage(PageItem *ite)
00711 {
00712     QString tmp = "";
00713     FPoint np, np1, np2;
00714     bool nPath = true;
00715     if (ite->imageClip.size() > 3)
00716         {
00717         for (uint poi=0; poi<ite->imageClip.size()-3; poi += 4)
00718             {
00719             if (ite->imageClip.point(poi).x() > 900000)
00720                 {
00721                 tmp += "Z ";
00722                 nPath = true;
00723                 continue;
00724                 }
00725             if (nPath)
00726                 {
00727                 np = ite->imageClip.point(poi);
00728                 tmp += "M"+FToStr(np.x())+" "+FToStr(np.y())+" ";
00729                 nPath = false;
00730                 }
00731             np = ite->imageClip.point(poi+1);
00732             tmp += "C"+FToStr(np.x())+" "+FToStr(np.y())+" ";
00733             np1 = ite->imageClip.point(poi+3);
00734             tmp += FToStr(np1.x())+" "+FToStr(np1.y())+" ";
00735             np2 = ite->imageClip.point(poi+2);
00736             tmp += FToStr(np2.x())+" "+FToStr(np2.y())+" ";
00737             }
00738         }
00739     return tmp;
00740 }
00741 
00742 QString SVGExPlug::FToStr(double c)
00743 {
00744     QString cc;
00745     return cc.setNum(c);
00746 }
00747 
00748 QString SVGExPlug::IToStr(int c)
00749 {
00750     QString cc;
00751     return cc.setNum(c);
00752 }
00753 
00754 void SVGExPlug::SetTextProps(QDomElement *tp, ScText *hl)
00755 {
00756     int chst = hl->effects() & 127;
00757     if (hl->fillColor() != CommonStrings::None)
00758         tp->setAttribute("fill", SetColor(hl->fillColor(), hl->fillShade()));
00759     else
00760         tp->setAttribute("fill", "none");
00761     if ((hl->strokeColor() != CommonStrings::None) && (chst & 4))
00762     {
00763         tp->setAttribute("stroke", SetColor(hl->strokeColor(), hl->strokeShade()));
00764         tp->setAttribute("stroke-width", FToStr(hl->font().strokeWidth(hl->fontSize() / 10.0)));
00765     }
00766     else
00767         tp->setAttribute("stroke", "none");
00768     tp->setAttribute("font-size", (hl->fontSize() / 10.0));
00769     tp->setAttribute("font-family", hl->font().family());
00770     if (chst != 0)
00771     {
00772         if (chst & 64)
00773             tp->setAttribute("font-variant", "small-caps");
00774         if (chst & 32)
00775             tp->setAttribute("font-weight", "bold");
00776         if (chst & 16)
00777             tp->setAttribute("text-decoration", "line-through");
00778         if (chst & 8)
00779             tp->setAttribute("text-decoration", "underline");
00780     }
00781 }
00782 
00783 QString SVGExPlug::SetColor(QString farbe, int shad)
00784 {
00785     const ScColor& col = m_Doc->PageColors[farbe];
00786     return ScColorEngine::getShadeColorProof(col, m_Doc, shad).name();
00787 }
00788 
00789 QString SVGExPlug::GetMultiStroke(struct SingleLine *sl, PageItem *Item)
00790 {
00791     QString tmp = "fill:none; ";
00792     tmp += "stroke:"+SetColor(sl->Color, sl->Shade)+"; ";
00793     if (Item->fillTransparency() != 0)
00794         tmp += " stroke-opacity:"+FToStr(1.0 - Item->fillTransparency())+"; ";
00795     tmp += "stroke-width:"+FToStr(sl->Width)+"; ";
00796     tmp += "stroke-linecap:";
00797     switch (static_cast<Qt::PenCapStyle>(sl->LineEnd))
00798         {
00799         case Qt::FlatCap:
00800             tmp += "butt;";
00801             break;
00802         case Qt::SquareCap:
00803             tmp += "square;";
00804             break;
00805         case Qt::RoundCap:
00806             tmp += "round;";
00807             break;
00808