00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <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
00073
00074 languageChange();
00075 }
00076
00077 SVGExportPlugin::~SVGExportPlugin() {};
00078
00079 void SVGExportPlugin::languageChange()
00080 {
00081
00082
00083
00084 m_actionInfo.name = "ExportAsSVG";
00085
00086 m_actionInfo.text = tr("Save as &SVG...");
00087
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
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