00001
00002
00003
00004
00005
00006
00007
00008 #include <QCursor>
00009 #include <QDrag>
00010 #include <QFile>
00011 #include <QList>
00012 #include <QMimeData>
00013 #include <QPainterPath>
00014 #include <QRegExp>
00015 #include <cmath>
00016 #include <zlib.h>
00017
00018 #include "color.h"
00019 #include "commonstrings.h"
00020 #include "customfdialog.h"
00021 #include "fonts/scfontmetrics.h"
00022 #include "fpointarray.h"
00023 #include "loadsaveplugin.h"
00024 #include "menumanager.h"
00025 #include "pageitem.h"
00026 #include "prefsfile.h"
00027 #include "prefsmanager.h"
00028 #include "propertiespalette.h"
00029 #include "sccolorengine.h"
00030 #include "scconfig.h"
00031 #include "scraction.h"
00032 #include "scribus.h"
00033 #include "scribusXml.h"
00034 #include "scribuscore.h"
00035 #include "scribusdoc.h"
00036 #include "selection.h"
00037 #include "svgplugin.h"
00038 #include "undomanager.h"
00039 #include "util.h"
00040 #include "util_formats.h"
00041 #include "util_icon.h"
00042 #include "util_math.h"
00043
00044
00045 using namespace std;
00046
00047 int svgimplugin_getPluginAPIVersion()
00048 {
00049 return PLUGIN_API_VERSION;
00050 }
00051
00052 ScPlugin* svgimplugin_getPlugin()
00053 {
00054 SVGImportPlugin* plug = new SVGImportPlugin();
00055 Q_CHECK_PTR(plug);
00056 return plug;
00057 }
00058
00059 void svgimplugin_freePlugin(ScPlugin* plugin)
00060 {
00061 SVGImportPlugin* plug = dynamic_cast<SVGImportPlugin*>(plugin);
00062 Q_ASSERT(plug);
00063 delete plug;
00064 }
00065
00066 SVGImportPlugin::SVGImportPlugin() : LoadSavePlugin(),
00067 importAction(new ScrAction(ScrAction::DLL, QPixmap(), QPixmap(), "", QKeySequence(), this))
00068 {
00069
00070
00071
00072 languageChange();
00073 }
00074
00075 void SVGImportPlugin::addToMainWindowMenu(ScribusMainWindow *mw)
00076 {
00077 importAction->setEnabled(true);
00078 connect( importAction, SIGNAL(triggered()), SLOT(import()) );
00079 mw->scrMenuMgr->addMenuItem(importAction, "FileImport");
00080 }
00081
00082 SVGImportPlugin::~SVGImportPlugin()
00083 {
00084 unregisterAll();
00085 };
00086
00087 void SVGImportPlugin::languageChange()
00088 {
00089 importAction->setText( tr("Import &SVG..."));
00090
00091 unregisterAll();
00092 registerFormats();
00093 }
00094
00095 const QString SVGImportPlugin::fullTrName() const
00096 {
00097 return QObject::tr("SVG Import");
00098 }
00099
00100 const ScActionPlugin::AboutData* SVGImportPlugin::getAboutData() const
00101 {
00102 AboutData* about = new AboutData;
00103 about->authors = "Franz Schmid <franz@scribus.info>";
00104 about->shortDescription = tr("Imports SVG Files");
00105 about->description = tr("Imports most SVG files into the current document,\nconverting their vector data into Scribus objects.");
00106 about->license = "GPL";
00107 Q_CHECK_PTR(about);
00108 return about;
00109 }
00110
00111 void SVGImportPlugin::deleteAboutData(const AboutData* about) const
00112 {
00113 Q_ASSERT(about);
00114 delete about;
00115 }
00116
00117 void SVGImportPlugin::registerFormats()
00118 {
00119 FileFormat fmt(this);
00120 fmt.trName = FormatsManager::instance()->nameOfFormat(FormatsManager::SVG);
00121 fmt.formatId = FORMATID_SVGIMPORT;
00122 fmt.filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::SVG);
00123 fmt.nameMatch = QRegExp("\\."+FormatsManager::instance()->extensionListForFormat(FormatsManager::SVG, 1)+"$", Qt::CaseInsensitive);
00124 fmt.load = true;
00125 fmt.save = false;
00126 fmt.mimeTypes = FormatsManager::instance()->mimetypeOfFormat(FormatsManager::SVG);
00127 fmt.priority = 64;
00128 registerFormat(fmt);
00129 }
00130
00131 bool SVGImportPlugin::fileSupported(QIODevice* , const QString & fileName) const
00132 {
00133
00134 return true;
00135 }
00136
00137 bool SVGImportPlugin::loadFile(const QString & fileName, const FileFormat & , int flags, int )
00138 {
00139
00140 return import(fileName, flags);
00141 }
00142
00143 bool SVGImportPlugin::import(QString filename, int flags)
00144 {
00145 if (!checkFlags(flags))
00146 return false;
00147 m_Doc=ScCore->primaryMainWindow()->doc;
00148 ScribusMainWindow* mw=(m_Doc==0) ? ScCore->primaryMainWindow() : m_Doc->scMW();
00149 if (filename.isEmpty())
00150 {
00151 flags |= lfInteractive;
00152 PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("SVGPlugin");
00153 QString wdir = prefs->get("wdir", ".");
00154 CustomFDialog diaf(mw, wdir, QObject::tr("Open"), FormatsManager::instance()->fileDialogFormatList(FormatsManager::SVG));
00155 if (diaf.exec())
00156 {
00157 filename = diaf.selectedFile();
00158 prefs->set("wdir", filename.left(filename.lastIndexOf("/")));
00159 }
00160 else
00161 return true;
00162 }
00163
00164 UndoTransaction* activeTransaction = NULL;
00165 bool emptyDoc = (m_Doc == NULL);
00166 if (UndoManager::undoEnabled() && !emptyDoc)
00167 {
00168 activeTransaction = new UndoTransaction(UndoManager::instance()->beginTransaction(m_Doc->currentPage()->getUName(),Um::IImageFrame,Um::ImportSVG, filename, Um::ISVG));
00169 }
00170 else if (UndoManager::undoEnabled() && emptyDoc)
00171 UndoManager::instance()->setUndoEnabled(false);
00172 SVGPlug *dia = new SVGPlug(mw, flags);
00173 dia->import(filename, flags);
00174 Q_CHECK_PTR(dia);
00175 if (activeTransaction)
00176 {
00177 activeTransaction->commit();
00178 delete activeTransaction;
00179 activeTransaction = NULL;
00180 }
00181 else if (UndoManager::undoEnabled() && emptyDoc)
00182 UndoManager::instance()->setUndoEnabled(true);
00183 if (dia->importCanceled)
00184 {
00185 if (dia->importFailed)
00186 QMessageBox::warning(mw, CommonStrings::trWarning, tr("The file could not be imported"), 1, 0, 0);
00187 else if (dia->unsupported)
00188 QMessageBox::warning(mw, CommonStrings::trWarning, tr("SVG file contains some unsupported features"), 1, 0, 0);
00189 }
00190
00191 delete dia;
00192 return true;
00193 }
00194
00195 SVGPlug::SVGPlug( ScribusMainWindow* mw, int flags ) :
00196 QObject(mw)
00197 {
00198 tmpSel=new Selection(this, false);
00199 m_Doc=mw->doc;
00200 unsupported = false;
00201 importFailed = false;
00202 importCanceled = true;
00203 importedColors.clear();
00204 docDesc = "";
00205 docTitle = "";
00206 groupLevel = 0;
00207 interactive = (flags & LoadSavePlugin::lfInteractive);
00208
00209 }
00210
00211 bool SVGPlug::import(QString fname, int flags)
00212 {
00213 if (!loadData(fname))
00214 return false;
00215 QString CurDirP = QDir::currentPath();
00216 QFileInfo efp(fname);
00217 QDir::setCurrent(efp.path());
00218 convert(flags);
00219 QDir::setCurrent(CurDirP);
00220 return true;
00221 }
00222
00223 bool SVGPlug::loadData(QString fName)
00224 {
00225 QString f("");
00226 bool isCompressed = false;
00227 QByteArray bb(3, ' ');
00228 QFile fi(fName);
00229 if (fi.open(QIODevice::ReadOnly))
00230 {
00231 fi.read(bb.data(), 2);
00232 fi.close();
00233
00234 if ((QChar(bb[0]) == QChar(0x1F)) && (QChar(bb[1]) == QChar(0x8B)))
00235 isCompressed = true;
00236 }
00237 if ((fName.right(2) == "gz") || (isCompressed))
00238 {
00239 gzFile gzDoc;
00240 char buff[4097];
00241 int i;
00242 gzDoc = gzopen(fName.toLatin1().constData(),"rb");
00243 if(gzDoc == NULL)
00244 return false;
00245 while((i = gzread(gzDoc,&buff,4096)) > 0)
00246 {
00247 buff[i] = '\0';
00248 f.append(buff);
00249 }
00250 gzclose(gzDoc);
00251 }
00252 else
00253 loadText(fName, &f);
00254 return inpdoc.setContent(f);
00255 }
00256
00257 void SVGPlug::convert(int flags)
00258 {
00259 bool ret = false;
00260 SvgStyle *gc = new SvgStyle;
00261 QDomElement docElem = inpdoc.documentElement();
00262 QSize wh = parseWidthHeight(docElem);
00263 double width = wh.width();
00264 double height = wh.height();
00265 if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
00266 {
00267 m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
00268 m_Doc->addPage(0);
00269 m_Doc->view()->addPage(0);
00270 }
00271 else
00272 {
00273 if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
00274 {
00275 m_Doc=ScCore->primaryMainWindow()->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
00276 ScCore->primaryMainWindow()->HaveNewDoc();
00277 ret = true;
00278 }
00279 }
00280 if ((ret) || (!interactive))
00281 {
00282 if (width > height)
00283 m_Doc->PageOri = 1;
00284 else
00285 m_Doc->PageOri = 0;
00286 m_Doc->m_pageSize = "Custom";
00287 }
00288 FPoint minSize = m_Doc->minCanvasCoordinate;
00289 FPoint maxSize = m_Doc->maxCanvasCoordinate;
00290 FPoint cOrigin = m_Doc->view()->canvasOrigin();
00291 m_Doc->view()->Deselect();
00292 m_Doc->setLoading(true);
00293 m_Doc->DoDrawing = false;
00294 m_Doc->view()->updatesOn(false);
00295 m_Doc->scMW()->ScriptRunning = true;
00296 qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
00297 gc->FontFamily = m_Doc->toolSettings.defFont;
00298 if (!m_Doc->PageColors.contains("Black"))
00299 m_Doc->PageColors.insert("Black", ScColor(0, 0, 0, 255));
00300 m_gc.push( gc );
00301 viewTransformX = 0;
00302 viewTransformY = 0;
00303 viewScaleX = 1;
00304 viewScaleY = 1;
00305 if( !docElem.attribute( "viewBox" ).isEmpty() )
00306 {
00307 QString viewbox( docElem.attribute( "viewBox" ) );
00308 QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', QString::SkipEmptyParts );
00309 if (points.size() > 3)
00310 {
00311 QMatrix matrix;
00312 QSize wh2 = parseWidthHeight(docElem);
00313 double w2 = wh2.width();
00314 double h2 = wh2.height();
00315 addGraphicContext();
00316 viewTransformX = points[0].toDouble();
00317 viewTransformY = points[1].toDouble();
00318 viewScaleX = w2 / points[2].toDouble();
00319 viewScaleY = h2 / points[3].toDouble();
00320 matrix.translate(viewTransformX, viewTransformY);
00321 matrix.scale(viewScaleX, viewScaleY);
00322 m_gc.top()->matrix = matrix;
00323 }
00324 }
00325 QList<PageItem*> Elements = parseGroup( docElem );
00326 if (flags & LoadSavePlugin::lfCreateDoc)
00327 {
00328 m_Doc->documentInfo.setTitle(docTitle);
00329 m_Doc->documentInfo.setComments(docDesc);
00330 }
00331 tmpSel->clear();
00332 if (Elements.count() == 0)
00333 {
00334 importFailed = true;
00335 if (importedColors.count() != 0)
00336 {
00337 for (int cd = 0; cd < importedColors.count(); cd++)
00338 {
00339 m_Doc->PageColors.remove(importedColors[cd]);
00340 }
00341 }
00342 }
00343 if (Elements.count() > 1)
00344 {
00345 bool isGroup = true;
00346 int firstElem = -1;
00347 if (Elements.at(0)->Groups.count() != 0)
00348 firstElem = Elements.at(0)->Groups.top();
00349 for (int bx = 0; bx < Elements.count(); ++bx)
00350 {
00351 PageItem* bxi = Elements.at(bx);
00352 if (bxi->Groups.count() != 0)
00353 {
00354 if (bxi->Groups.top() != firstElem)
00355 isGroup = false;
00356 }
00357 else
00358 isGroup = false;
00359 }
00360 if (!isGroup)
00361 {
00362 double minx = 99999.9;
00363 double miny = 99999.9;
00364 double maxx = -99999.9;
00365 double maxy = -99999.9;
00366 uint lowestItem = 999999;
00367 uint highestItem = 0;
00368 for (int a = 0; a < Elements.count(); ++a)
00369 {
00370 Elements.at(a)->Groups.push(m_Doc->GroupCounter);
00371 PageItem* currItem = Elements.at(a);
00372 lowestItem = qMin(lowestItem, currItem->ItemNr);
00373 highestItem = qMax(highestItem, currItem->ItemNr);
00374 double lw = currItem->lineWidth() / 2.0;
00375 if (currItem->rotation() != 0)
00376 {
00377 FPointArray pb;
00378 pb.resize(0);
00379 pb.addPoint(FPoint(currItem->xPos()-lw, currItem->yPos()-lw));
00380 pb.addPoint(FPoint(currItem->width()+lw*2.0, -lw, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00381 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));
00382 pb.addPoint(FPoint(-lw, currItem->height()+lw*2.0, currItem->xPos()-lw, currItem->yPos()-lw, currItem->rotation(), 1.0, 1.0));
00383 for (uint pc = 0; pc < 4; ++pc)
00384 {
00385 minx = qMin(minx, pb.point(pc).x());
00386 miny = qMin(miny, pb.point(pc).y());
00387 maxx = qMax(maxx, pb.point(pc).x());
00388 maxy = qMax(maxy, pb.point(pc).y());
00389 }
00390 }
00391 else
00392 {
00393 minx = qMin(minx, currItem->xPos()-lw);
00394 miny = qMin(miny, currItem->yPos()-lw);
00395 maxx = qMax(maxx, currItem->xPos()-lw + currItem->width()+lw*2.0);
00396 maxy = qMax(maxy, currItem->yPos()-lw + currItem->height()+lw*2.0);
00397 }
00398 }
00399 double gx = minx;
00400 double gy = miny;
00401 double gw = maxx - minx;
00402 double gh = maxy - miny;
00403 PageItem *high = m_Doc->Items->at(highestItem);
00404 int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->toolSettings.dBrush, m_Doc->toolSettings.dPen, true);
00405 PageItem *neu = m_Doc->Items->takeAt(z);
00406 m_Doc->Items->insert(lowestItem, neu);
00407 neu->Groups.push(m_Doc->GroupCounter);
00408 neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
00409 neu->isGroupControl = true;
00410 neu->groupsLastItem = high;
00411 for (int a = 0; a < m_Doc->Items->count(); ++a)
00412 {
00413 m_Doc->Items->at(a)->ItemNr = a;
00414 }
00415 neu->setRedrawBounding();
00416 neu->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00417 Elements.prepend(neu);
00418 m_Doc->GroupCounter++;
00419 }
00420 }
00421 m_Doc->DoDrawing = true;
00422 m_Doc->scMW()->ScriptRunning = false;
00423 if (interactive)
00424 m_Doc->setLoading(false);
00425 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
00426 if ((Elements.count() > 0) && (!ret) && (interactive))
00427 {
00428 if (flags & LoadSavePlugin::lfScripted)
00429 {
00430 bool loadF = m_Doc->isLoading();
00431 m_Doc->setLoading(false);
00432 m_Doc->changed();
00433 m_Doc->setLoading(loadF);
00434 for (int dre=0; dre<Elements.count(); ++dre)
00435 {
00436 m_Doc->m_Selection->addItem(Elements.at(dre), true);
00437 }
00438 m_Doc->m_Selection->setGroupRect();
00439 m_Doc->view()->updatesOn(true);
00440 importCanceled = false;
00441 }
00442 else
00443 {
00444 m_Doc->DragP = true;
00445 m_Doc->DraggedElem = 0;
00446 m_Doc->DragElements.clear();
00447 for (int dre=0; dre<Elements.count(); ++dre)
00448 {
00449 m_Doc->DragElements.append(Elements.at(dre)->ItemNr);
00450 tmpSel->addItem(Elements.at(dre), true);
00451 }
00452 ScriXmlDoc *ss = new ScriXmlDoc();
00453 tmpSel->setGroupRect();
00454 QMimeData* md = new QMimeData();
00455 md->setText(ss->WriteElem(m_Doc, m_Doc->view(), tmpSel));
00456 QDrag* dr = new QDrag(m_Doc->view()->viewport());
00457 dr->setMimeData(md);
00458 #ifndef QT_WS_MAC
00459
00460 m_Doc->itemSelection_DeleteItem(tmpSel);
00461 #endif
00462
00463
00464 m_Doc->minCanvasCoordinate = minSize;
00465 m_Doc->maxCanvasCoordinate = maxSize;
00466 m_Doc->view()->adjustCanvas(qRound((maxSize.x() - minSize.x()) * m_Doc->view()->scale()), qRound((maxSize.y() - minSize.y()) * m_Doc->view()->scale()), 0, 0);
00467 m_Doc->view()->setCanvasOrigin(cOrigin.x(), cOrigin.y());
00468 m_Doc->view()->updatesOn(true);
00469 m_Doc->view()->updateCanvas();
00470 const QPixmap& dragCursor = loadIcon("DragPix.xpm");
00471 dr->setDragCursor(dragCursor, Qt::CopyAction);
00472 dr->setDragCursor(dragCursor, Qt::MoveAction);
00473 dr->setDragCursor(dragCursor, Qt::LinkAction);
00474 dr->exec();
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 delete ss;
00489 m_Doc->DragP = false;
00490 m_Doc->DraggedElem = 0;
00491 m_Doc->DragElements.clear();
00492 }
00493 }
00494 else
00495 {
00496 bool loadF = m_Doc->isLoading();
00497 m_Doc->setLoading(false);
00498 m_Doc->changed();
00499 m_Doc->reformPages();
00500 m_Doc->view()->updatesOn(true);
00501 m_Doc->setLoading(loadF);
00502 }
00503 }
00504
00505 void SVGPlug::addGraphicContext()
00506 {
00507 SvgStyle *gc = new SvgStyle;
00508 if ( m_gc.top() )
00509 *gc = *( m_gc.top() );
00510 m_gc.push( gc );
00511 }
00512
00513 void SVGPlug::setupNode( const QDomElement &e )
00514 {
00515 addGraphicContext();
00516 setupTransform( e );
00517 parseStyle(m_gc.top(), e);
00518 }
00519
00520 void SVGPlug::setupTransform( const QDomElement &e )
00521 {
00522 SvgStyle *gc = m_gc.top();
00523 QMatrix mat = parseTransform( e.attribute( "transform" ) );
00524 if (!e.attribute("transform").isEmpty())
00525 gc->matrix = mat * gc->matrix;
00526 }
00527
00528 void SVGPlug::finishNode( const QDomNode &e, PageItem* item)
00529 {
00530 SvgStyle *gc = m_gc.top();
00531 QMatrix gcm = gc->matrix;
00532 double BaseX = m_Doc->currentPage()->xOffset();
00533 double BaseY = m_Doc->currentPage()->yOffset();
00534 double coeff1 = sqrt(gcm.m11() * gcm.m11() + gcm.m12() * gcm.m12());
00535 double coeff2 = sqrt(gcm.m21() * gcm.m21() + gcm.m22() * gcm.m22());
00536 switch (item->itemType())
00537 {
00538 case PageItem::ImageFrame:
00539 {
00540 QMatrix mm = gc->matrix;
00541 item->moveBy(mm.dx(), mm.dy());
00542 item->setWidthHeight(item->width() * mm.m11(), item->height() * mm.m22());
00543 item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
00544 if (item->PicAvail)
00545 item->setImageXYScale(item->width() / item->pixm.width(), item->height() / item->pixm.height());
00546 break;
00547 }
00548 case PageItem::TextFrame:
00549 {
00550 QMatrix mm = gc->matrix;
00551 item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
00552 }
00553 break;
00554 default:
00555 {
00556 item->ClipEdited = true;
00557 item->FrameType = 3;
00558 QMatrix mm = gc->matrix;
00559 item->PoLine.map(mm);
00560
00561
00562
00563
00564
00565
00566
00567 item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
00568 FPoint wh = getMaxClipF(&item->PoLine);
00569 item->setWidthHeight(wh.x(), wh.y());
00570
00571
00572
00573
00574 m_Doc->AdjustItemSize(item);
00575 break;
00576 }
00577 }
00578 item->setRedrawBounding();
00579 item->OwnPage = m_Doc->OnPage(item);
00580 if (e.isElement())
00581 {
00582 QString nodeId = e.toElement().attribute("id");
00583 if( !nodeId.isEmpty() )
00584 item->setItemName(" "+nodeId);
00585 }
00586 item->setFillTransparency( 1 - gc->FillOpacity * gc->Opacity );
00587 item->setLineTransparency( 1 - gc->StrokeOpacity * gc->Opacity );
00588 item->PLineEnd = gc->PLineEnd;
00589 item->PLineJoin = gc->PLineJoin;
00590 if (item->fillColor() == CommonStrings::None)
00591 item->setTextFlowMode(PageItem::TextFlowDisabled);
00592 else
00593 item->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
00594 item->DashOffset = gc->dashOffset;
00595 item->DashValues = gc->dashArray;
00596 if (gc->Gradient != 0)
00597 {
00598 if (gc->GradCo.Stops() > 1)
00599 {
00600 item->fill_gradient = gc->GradCo;
00601 if (!gc->CSpace)
00602 {
00603 item->GrStartX = gc->GX1 * item->width();
00604 item->GrStartY = gc->GY1 * item->height();
00605 item->GrEndX = gc->GX2 * item->width();
00606 item->GrEndY = gc->GY2 * item->height();
00607 double angle1 = atan2(gc->GY2-gc->GY1,gc->GX2-gc->GX1)*(180.0/M_PI);
00608 double angle2 = atan2(item->GrEndY - item->GrStartX, item->GrEndX - item->GrStartX)*(180.0/M_PI);
00609 double dx = item->GrStartX + (item->GrEndX - item->GrStartX) / 2.0;
00610 double dy = item->GrStartY + (item->GrEndY - item->GrStartY) / 2.0;
00611 QMatrix mm, mm2;
00612 if ((gc->GY1 < gc->GY2) && (gc->GX1 < gc->GX2))
00613 {
00614 mm.rotate(-angle2);
00615 mm2.rotate(angle1);
00616 }
00617 FPointArray gra;
00618 gra.setPoints(2, item->GrStartX-dx, item->GrStartY-dy, item->GrEndX-dx, item->GrEndY-dy);
00619 gra.map(mm*mm2);
00620 gra.translate(dx, dy);
00621 item->GrStartX = gra.point(0).x();
00622 item->GrStartY = gra.point(0).y();
00623 item->GrEndX = gra.point(1).x();
00624 item->GrEndY = gra.point(1).y();
00625 }
00626 else
00627 {
00628 QMatrix mm = gc->matrix;
00629 mm = gc->matrixg * mm;
00630 FPointArray gra;
00631 gra.setPoints(2, gc->GX1, gc->GY1, gc->GX2, gc->GY2);
00632 gra.map(mm);
00633 gc->GX1 = gra.point(0).x();
00634 gc->GY1 = gra.point(0).y();
00635 gc->GX2 = gra.point(1).x();
00636 gc->GY2 = gra.point(1).y();
00637 item->GrStartX = gc->GX1 - item->xPos() + BaseX;
00638 item->GrStartY = gc->GY1 - item->yPos() + BaseY;
00639 item->GrEndX = gc->GX2 - item->xPos() + BaseX;
00640 item->GrEndY = gc->GY2 - item->yPos() + BaseY;
00641 }
00642 item->GrType = gc->Gradient;
00643 }
00644 else
00645 {
00646 item->GrType = 0;
00647 QList<VColorStop*> cstops = gc->GradCo.colorStops();
00648 item->setFillColor(cstops.at(0)->name);
00649 item->setFillShade(cstops.at(0)->shade);
00650 }
00651 }
00652 }
00653
00654 bool SVGPlug::isIgnorableNode( const QDomElement &e )
00655 {
00656 QString nodeName(e.tagName());
00657 return isIgnorableNodeName(nodeName);
00658 }
00659
00660 bool SVGPlug::isIgnorableNodeName( const QString &n )
00661 {
00662 if (n.startsWith("sodipodi") || n.startsWith("inkscape") || n == "metadata")
00663 return true;
00664 return false;
00665 }
00666
00667 FPoint SVGPlug::parseTextPosition(const QDomElement &e)
00668 {
00669
00670 QString xatt = e.attribute( "x", "0" );
00671 QString yatt = e.attribute( "y", "0" );
00672 if ( xatt.contains(',') || xatt.contains(' ') )
00673 {
00674 xatt.replace(QChar(','), QChar(' '));
00675 QStringList xl(xatt.split(QChar(' '), QString::SkipEmptyParts));
00676 xatt = xl.first();
00677 }
00678 if ( yatt.contains(',') || yatt.contains(' ') )
00679 {
00680 yatt.replace(QChar(','), QChar(' '));
00681 QStringList yl(yatt.split(QChar(' '), QString::SkipEmptyParts));
00682 yatt = yl.first();
00683 }
00684 double x = parseUnit( xatt );
00685 double y = parseUnit( yatt );
00686 return FPoint(x, y);
00687 }
00688
00689 QSize SVGPlug::parseWidthHeight(const QDomElement &e)
00690 {
00691 QSize size(550, 841);
00692 QString sw = e.attribute("width", "100%");
00693 QString sh = e.attribute("height", "100%");
00694 double w = 550, h = 841;
00695 if (!sw.isEmpty())
00696 w = sw.endsWith("%") ? fromPercentage(sw) : parseUnit(sw);
00697 if (!sh.isEmpty())
00698 h = sh.endsWith("%") ? fromPercentage(sh) : parseUnit(sh);
00699 if (!e.attribute("viewBox").isEmpty())
00700 {
00701 QRect viewBox = parseViewBox(e);
00702 double scw = (viewBox.width() > 0 && viewBox.height() > 0) ? viewBox.width() : size.width();
00703 double sch = (viewBox.width() > 0 && viewBox.height() > 0) ? viewBox.height() : size.height();
00704 w *= (sw.endsWith("%") ? scw : 1.0);
00705 h *= (sh.endsWith("%") ? sch : 1.0);
00706 }
00707 else
00708 {
00709 w *= (sw.endsWith("%") ? size.width() : 1.0);
00710 h *= (sh.endsWith("%") ? size.height() : 1.0);
00711 }
00712
00713 if (w > 10000 || h > 10000)
00714 {
00715 double m = max(w, h);
00716 w = w / m * 842;
00717 h = h / m * 842;
00718 }
00719 size.setWidth(qRound(w));
00720 size.setHeight(qRound(h));
00721 return size;
00722 }
00723
00724 QRect SVGPlug::parseViewBox(const QDomElement &e)
00725 {
00726 QRect box(0, 0, 0, 0);
00727 if ( !e.attribute( "viewBox" ).isEmpty() )
00728 {
00729 QString viewbox( e.attribute( "viewBox" ) );
00730 QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', QString::SkipEmptyParts );
00731 if (points.size() > 3)
00732 {
00733 double left = points[0].toDouble();
00734 double bottom = points[1].toDouble();
00735 double width = points[2].toDouble();
00736 double height = points[3].toDouble();
00737 box.setCoords((int) left, (int) bottom, (int) (left + width), (int) (bottom + height));
00738 }
00739 }
00740 return box;
00741 }
00742
00743 void SVGPlug::parseDefs(const QDomElement &e)
00744 {
00745 for ( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
00746 {
00747 QDomElement b = n.toElement();
00748 if ( b.isNull() )
00749 continue;
00750 SvgStyle svgStyle;
00751 parseStyle( &svgStyle, b );
00752 if ( !svgStyle.Display)
00753 continue;
00754 QString STag2 = b.tagName();
00755 if ( STag2 == "g" )
00756 {
00757 QString id = b.attribute("id", "");
00758 if (!id.isEmpty())
00759 m_nodeMap.insert(id, b);
00760 parseDefs(b);
00761 }
00762 else if ( STag2 == "linearGradient" || STag2 == "radialGradient" )
00763 parseGradient( b );
00764 else if (STag2 == "clipPath")
00765 parseClipPath(b);
00766 else if ( b.hasAttribute("id") )
00767 {
00768 QString id = b.attribute("id");
00769 if (!id.isEmpty())
00770 m_nodeMap.insert(id, b);
00771 }
00772 }
00773 }
00774
00775 void SVGPlug::parseClipPath(const QDomElement &e)
00776 {
00777 QString id(e.attribute("id"));
00778 if (!id.isEmpty())
00779 {
00780 FPointArray clip;
00781 QDomNode n2 = e.firstChild();
00782 QDomElement b2 = n2.toElement();
00783 while (b2.nodeName() == "use")
00784 b2 = getReferencedNode(b2);
00785 if (b2.nodeName() == "path")
00786 parseSVG( b2.attribute( "d" ), &clip );
00787 else if (b2.nodeName() == "rect")
00788 {
00789 double width = parseUnit( b2.attribute( "width" ));
00790 double height = parseUnit( b2.attribute( "height" ) );
00791 clip.addQuadPoint(0.0, 0.0, 0.0, 0.0, width, 0.0, width, 0.0);
00792 clip.addQuadPoint(width, 0.0, width, 0.0, width, height, width, height);
00793 clip.addQuadPoint(width, height, width, height, 0.0, height, 0.0, height);
00794 clip.addQuadPoint(0.0, height, 0.0, height, 0.0, 0.0, 0.0, 0.0);
00795 }
00796 if (clip.size() >= 2)
00797 m_clipPaths.insert(id, clip);
00798 }
00799 }
00800
00801 void SVGPlug::parseClipPathAttr(const QDomElement &e, FPointArray& clipPath)
00802 {
00803 clipPath.resize(0);
00804 if (e.hasAttribute("clip-path"))
00805 {
00806 QString attr = e.attribute("clip-path");
00807 if (attr.startsWith( "url("))
00808 {
00809 unsigned int start = attr.indexOf("#") + 1;
00810 unsigned int end = attr.lastIndexOf(")");
00811 QString key = attr.mid(start, end - start);
00812 QMap<QString, FPointArray>::iterator it = m_clipPaths.find(key);
00813 if (it != m_clipPaths.end())
00814 clipPath = it.value().copy();
00815 }
00816 }
00817 }
00818
00819 QList<PageItem*> SVGPlug::parseGroup(const QDomElement &e)
00820 {
00821 FPointArray clipPath;
00822 QList<PageItem*> GElements, gElements;
00823 double BaseX = m_Doc->currentPage()->xOffset();
00824 double BaseY = m_Doc->currentPage()->yOffset();
00825 groupLevel++;