Rev 3544 | Rev 3643 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
68 | Franz | 1 | #include "svgplugin.h" |
2 | #include "svgplugin.moc" |
||
2688 | craig | 3 | |
4 | #include "scconfig.h" |
||
5 | |||
68 | Franz | 6 | #include "customfdialog.h" |
7 | #include "color.h" |
||
3207 | craig | 8 | #include "scribus.h" |
68 | Franz | 9 | #include "scribusXml.h" |
265 | Franz | 10 | #include "mpalette.h" |
415 | Franz | 11 | #include "prefsfile.h" |
68 | Franz | 12 | #include <qfile.h> |
13 | #include <qtextstream.h> |
||
1525 | cbradney | 14 | #include <qdragobject.h> |
68 | Franz | 15 | #include <qregexp.h> |
282 | Franz | 16 | #include <qcursor.h> |
68 | Franz | 17 | #include <cmath> |
18 | #ifdef HAVE_LIBZ |
||
19 | #include <zlib.h> |
||
20 | #endif |
||
1435 | tsoots | 21 | #include "undomanager.h" |
2529 | craig | 22 | #include "util.h" |
23 | #include "scfontmetrics.h" |
||
2834 | cbradney | 24 | #include "prefsmanager.h" |
3207 | craig | 25 | #include "pageitem.h" |
26 | #include "scribusdoc.h" |
||
3210 | craig | 27 | #include "fpointarray.h" |
68 | Franz | 28 | |
504 | cbradney | 29 | using namespace std; |
30 | |||
3207 | craig | 31 | int svgimplugin_getPluginAPIVersion() |
68 | Franz | 32 | { |
3207 | craig | 33 | return PLUGIN_API_VERSION; |
68 | Franz | 34 | } |
35 | |||
3207 | craig | 36 | ScPlugin* svgimplugin_getPlugin() |
68 | Franz | 37 | { |
3207 | craig | 38 | SVGImportPlugin* plug = new SVGImportPlugin(); |
39 | Q_CHECK_PTR(plug); |
||
40 | return plug; |
||
68 | Franz | 41 | } |
42 | |||
3207 | craig | 43 | void svgimplugin_freePlugin(ScPlugin* plugin) |
512 | fschmid | 44 | { |
3207 | craig | 45 | SVGImportPlugin* plug = dynamic_cast<SVGImportPlugin*>(plugin); |
46 | Q_ASSERT(plug); |
||
47 | delete plug; |
||
512 | fschmid | 48 | } |
49 | |||
3487 | craig | 50 | SVGImportPlugin::SVGImportPlugin() : LoadSavePlugin() |
1208 | cbradney | 51 | { |
3207 | craig | 52 | // Set action info in languageChange, so we only have to do |
53 | // it in one place. |
||
54 | languageChange(); |
||
1208 | cbradney | 55 | } |
56 | |||
3207 | craig | 57 | SVGImportPlugin::~SVGImportPlugin() {}; |
58 | |||
59 | void SVGImportPlugin::languageChange() |
||
1208 | cbradney | 60 | { |
3207 | craig | 61 | // Note that we leave the unused members unset. They'll be initialised |
62 | // with their default ctors during construction. |
||
63 | // Action name |
||
64 | m_actionInfo.name = "ImportSVG"; |
||
65 | // Action text for menu, including accel |
||
66 | m_actionInfo.text = tr("Import &SVG..."); |
||
67 | // Menu |
||
68 | m_actionInfo.menu = "FileImport"; |
||
69 | m_actionInfo.enabledOnStartup = true; |
||
1208 | cbradney | 70 | } |
71 | |||
3207 | craig | 72 | const QString SVGImportPlugin::fullTrName() const |
1208 | cbradney | 73 | { |
3207 | craig | 74 | return QObject::tr("SVG Import"); |
1208 | cbradney | 75 | } |
76 | |||
3207 | craig | 77 | const ScActionPlugin::AboutData* SVGImportPlugin::getAboutData() const |
1208 | cbradney | 78 | { |
3241 | craig | 79 | AboutData* about = new AboutData; |
3344 | fschmid | 80 | about->authors = "Franz Schmid <franz@scribus.info>"; |
3355 | cbradney | 81 | about->shortDescription = tr("Imports SVG Files"); |
3357 | cbradney | 82 | about->description = tr("Imports most SVG files into the current document,\nconverting their vector data into Scribus objects."); |
3344 | fschmid | 83 | about->license = "GPL"; |
3241 | craig | 84 | Q_CHECK_PTR(about); |
85 | return about; |
||
1208 | cbradney | 86 | } |
87 | |||
3241 | craig | 88 | void SVGImportPlugin::deleteAboutData(const AboutData* about) const |
1208 | cbradney | 89 | { |
3241 | craig | 90 | Q_ASSERT(about); |
91 | delete about; |
||
1208 | cbradney | 92 | } |
93 | |||
3487 | craig | 94 | QValueList<LoadSavePlugin::FormatSupport> SVGImportPlugin::supportedFormats() const |
95 | { |
||
96 | QValueList<FormatSupport> formats; |
||
97 | QString svgName = tr("Scalable Vector Graphics"); |
||
98 | FormatSupport fmt = { |
||
99 | svgName, "svgim", svgName + " (*.svg *.svgz)", |
||
100 | Format_Import|Format_Load, QStringList("image/svg+xml"), 64}; |
||
101 | formats.append(fmt); |
||
102 | return formats; |
||
103 | } |
||
104 | |||
105 | bool SVGImportPlugin::fileSupported(QIODevice* /* file */) const |
||
106 | { |
||
107 | // TODO: identify valid SVG |
||
108 | return true; |
||
109 | } |
||
110 | |||
202 | Franz | 111 | /*! |
3207 | craig | 112 | \fn void Run(QString filename) |
202 | Franz | 113 | \author Franz Schmid |
114 | \date |
||
115 | \brief Run the SVG import |
||
3207 | craig | 116 | \retval true for success |
202 | Franz | 117 | */ |
3207 | craig | 118 | bool SVGImportPlugin::run(QString filename) |
68 | Franz | 119 | { |
3207 | craig | 120 | bool interactive = false; |
121 | if (filename.isEmpty()) |
||
506 | fschmid | 122 | { |
3207 | craig | 123 | interactive = true; |
2856 | cbradney | 124 | PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("SVGPlugin"); |
506 | fschmid | 125 | QString wdir = prefs->get("wdir", "."); |
68 | Franz | 126 | #ifdef HAVE_LIBZ |
3207 | craig | 127 | CustomFDialog diaf(ScApp, wdir, QObject::tr("Open"), QObject::tr("SVG-Images (*.svg *.svgz);;All Files (*)")); |
68 | Franz | 128 | #else |
3207 | craig | 129 | CustomFDialog diaf(ScApp, wdir, QObject::tr("Open"), QObject::tr("SVG-Images (*.svg);;All Files (*)")); |
68 | Franz | 130 | #endif |
506 | fschmid | 131 | if (diaf.exec()) |
132 | { |
||
3207 | craig | 133 | filename = diaf.selectedFile(); |
134 | prefs->set("wdir", filename.left(filename.findRev("/"))); |
||
506 | fschmid | 135 | } |
136 | else |
||
3207 | craig | 137 | return true; |
415 | Franz | 138 | } |
3207 | craig | 139 | if (UndoManager::undoEnabled() && ScApp->HaveDoc) |
1439 | tsoots | 140 | { |
3207 | craig | 141 | UndoManager::instance()->beginTransaction(ScApp->doc->currentPage->getUName(),Um::IImageFrame,Um::ImportSVG, filename, Um::ISVG); |
1439 | tsoots | 142 | } |
3207 | craig | 143 | else if (UndoManager::undoEnabled() && !ScApp->HaveDoc) |
1439 | tsoots | 144 | UndoManager::instance()->setUndoEnabled(false); |
3207 | craig | 145 | SVGPlug *dia = new SVGPlug(filename, interactive); |
146 | Q_CHECK_PTR(dia); |
||
1435 | tsoots | 147 | if (UndoManager::undoEnabled()) |
148 | UndoManager::instance()->commit(); |
||
1439 | tsoots | 149 | else |
150 | UndoManager::instance()->setUndoEnabled(true); |
||
217 | Franz | 151 | delete dia; |
3207 | craig | 152 | return true; |
68 | Franz | 153 | } |
154 | |||
202 | Franz | 155 | /*! |
3207 | craig | 156 | \fn SVGPlug::SVGPlug( QString fName ) |
202 | Franz | 157 | \author Franz Schmid |
158 | \date |
||
159 | \brief Create the SVG importer window |
||
160 | \param fName QString |
||
161 | \retval SVGPlug plugin |
||
162 | */ |
||
3207 | craig | 163 | SVGPlug::SVGPlug( QString fName, bool isInteractive ) : |
164 | QObject(ScApp) |
||
68 | Franz | 165 | { |
3207 | craig | 166 | interactive = isInteractive; |
68 | Franz | 167 | QString f = ""; |
168 | #ifdef HAVE_LIBZ |
||
169 | if(fName.right(2) == "gz") |
||
217 | Franz | 170 | { |
68 | Franz | 171 | gzFile gzDoc; |
172 | char buff[4097]; |
||
173 | int i; |
||
174 | gzDoc = gzopen(fName.latin1(),"rb"); |
||
175 | if(gzDoc == NULL) |
||
176 | return; |
||
177 | while((i = gzread(gzDoc,&buff,4096)) > 0) |
||
217 | Franz | 178 | { |
68 | Franz | 179 | buff[i] = '\0'; |
180 | f.append(buff); |
||
217 | Franz | 181 | } |
68 | Franz | 182 | gzclose(gzDoc); |
217 | Franz | 183 | } |
68 | Franz | 184 | else |
185 | loadText(fName, &f); |
||
186 | #else |
||
187 | loadText(fName, &f); |
||
188 | #endif |
||
189 | if(!inpdoc.setContent(f)) |
||
190 | return; |
||
191 | m_gc.setAutoDelete( true ); |
||
192 | QString CurDirP = QDir::currentDirPath(); |
||
193 | QFileInfo efp(fName); |
||
194 | QDir::setCurrent(efp.dirPath()); |
||
195 | convert(); |
||
196 | QDir::setCurrent(CurDirP); |
||
197 | } |
||
198 | |||
202 | Franz | 199 | /*! |
200 | \fn void SVGPlug::convert() |
||
201 | \author Franz Schmid |
||
202 | \date |
||
203 | \brief |
||
204 | \param None |
||
205 | \retval None |
||
206 | */ |
||
68 | Franz | 207 | void SVGPlug::convert() |
208 | { |
||
209 | bool ret = false; |
||
210 | SvgStyle *gc = new SvgStyle; |
||
2607 | fschmid | 211 | Conversion = 0.8; |
68 | Franz | 212 | QDomElement docElem = inpdoc.documentElement(); |
456 | fschmid | 213 | double width = !docElem.attribute("width").isEmpty() ? parseUnit(docElem.attribute( "width" )) : 550.0; |
214 | double height = !docElem.attribute("height").isEmpty() ? parseUnit(docElem.attribute( "height" )) : 841.0; |
||
2607 | fschmid | 215 | Conversion = 0.8; |
3207 | craig | 216 | if (!interactive) |
217 | Franz | 217 | { |
3207 | craig | 218 | ScApp->doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false); |
219 | ScApp->view->addPage(0); |
||
217 | Franz | 220 | } |
506 | fschmid | 221 | else |
222 | { |
||
3207 | craig | 223 | if (!ScApp->HaveDoc) |
506 | fschmid | 224 | { |
3207 | craig | 225 | ScApp->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom"); |
506 | fschmid | 226 | ret = true; |
227 | } |
||
228 | } |
||
3207 | craig | 229 | if ((ret) || (!interactive)) |
550 | fschmid | 230 | { |
231 | if (width > height) |
||
3207 | craig | 232 | ScApp->doc->PageOri = 1; |
550 | fschmid | 233 | else |
3207 | craig | 234 | ScApp->doc->PageOri = 0; |
235 | ScApp->doc->PageSize = "Custom"; |
||
550 | fschmid | 236 | } |
3292 | cbradney | 237 | currDoc = ScApp->doc; |
238 | FPoint minSize = currDoc->minCanvasCoordinate; |
||
239 | FPoint maxSize = currDoc->maxCanvasCoordinate; |
||
3207 | craig | 240 | ScApp->view->Deselect(); |
68 | Franz | 241 | Elements.clear(); |
3292 | cbradney | 242 | currDoc->setLoading(true); |
243 | currDoc->DoDrawing = false; |
||
3207 | craig | 244 | ScApp->view->setUpdatesEnabled(false); |
245 | ScApp->ScriptRunning = true; |
||
282 | Franz | 246 | qApp->setOverrideCursor(QCursor(waitCursor), true); |
3292 | cbradney | 247 | gc->Family = currDoc->toolSettings.defFont; |
248 | if (!currDoc->PageColors.contains("Black")) |
||
249 | currDoc->PageColors.insert("Black", ScColor(0, 0, 0, 255)); |
||
68 | Franz | 250 | m_gc.push( gc ); |
1013 | fschmid | 251 | viewTransformX = 0; |
252 | viewTransformY = 0; |
||
253 | viewScaleX = 1; |
||
254 | viewScaleY = 1; |
||
255 | haveViewBox = false; |
||
256 | if( !docElem.attribute( "viewBox" ).isEmpty() ) |
||
257 | { |
||
2607 | fschmid | 258 | Conversion = 1.0; |
259 | double w2 = !docElem.attribute("width").isEmpty() ? parseUnit(docElem.attribute( "width" )) : 550.0; |
||
260 | double h2 = !docElem.attribute("height").isEmpty() ? parseUnit(docElem.attribute( "height" )) : 841.0; |
||
261 | Conversion = 0.8; |
||
1013 | fschmid | 262 | QString viewbox( docElem.attribute( "viewBox" ) ); |
263 | QStringList points = QStringList::split( ' ', viewbox.replace( QRegExp(","), " ").simplifyWhiteSpace() ); |
||
264 | viewTransformX = points[0].toDouble(); |
||
265 | viewTransformY = points[1].toDouble(); |
||
2607 | fschmid | 266 | viewScaleX = w2 / points[2].toDouble(); |
267 | viewScaleY = h2 / points[3].toDouble(); |
||
1013 | fschmid | 268 | haveViewBox = true; |
269 | } |
||
68 | Franz | 270 | parseGroup( docElem ); |
3207 | craig | 271 | ScApp->view->SelItem.clear(); |
302 | Franz | 272 | if (Elements.count() > 1) |
217 | Franz | 273 | { |
68 | Franz | 274 | for (uint a = 0; a < Elements.count(); ++a) |
217 | Franz | 275 | { |
3292 | cbradney | 276 | Elements.at(a)->Groups.push(currDoc->GroupCounter); |
217 | Franz | 277 | } |
3292 | cbradney | 278 | currDoc->GroupCounter++; |
217 | Franz | 279 | } |
3292 | cbradney | 280 | currDoc->DoDrawing = true; |
3207 | craig | 281 | ScApp->view->setUpdatesEnabled(true); |
282 | ScApp->ScriptRunning = false; |
||
283 | if (interactive) |
||
3292 | cbradney | 284 | currDoc->setLoading(false); |
282 | Franz | 285 | qApp->setOverrideCursor(QCursor(arrowCursor), true); |
3207 | craig | 286 | if ((Elements.count() > 0) && (!ret) && (interactive)) |
217 | Franz | 287 | { |
3292 | cbradney | 288 | currDoc->DragP = true; |
289 | currDoc->DraggedElem = 0; |
||
290 | currDoc->DragElements.clear(); |
||
68 | Franz | 291 | for (uint dre=0; dre<Elements.count(); ++dre) |
217 | Franz | 292 | { |
3292 | cbradney | 293 | currDoc->DragElements.append(Elements.at(dre)->ItemNr); |
3207 | craig | 294 | ScApp->view->SelItem.append(Elements.at(dre)); |
217 | Franz | 295 | } |
296 | ScriXmlDoc *ss = new ScriXmlDoc(); |
||
3207 | craig | 297 | ScApp->view->setGroupRect(); |
3292 | cbradney | 298 | QDragObject *dr = new QTextDrag(ss->WriteElem(&ScApp->view->SelItem, currDoc, ScApp->view), ScApp->view->viewport()); |
3207 | craig | 299 | ScApp->view->DeleteItem(); |
300 | ScApp->view->resizeContents(qRound((maxSize.x() - minSize.x()) * ScApp->view->getScale()), qRound((maxSize.y() - minSize.y()) * ScApp->view->getScale())); |
||
3292 | cbradney | 301 | ScApp->view->scrollBy(qRound((currDoc->minCanvasCoordinate.x() - minSize.x()) * ScApp->view->getScale()), qRound((currDoc->minCanvasCoordinate.y() - minSize.y()) * ScApp->view->getScale())); |
302 | currDoc->minCanvasCoordinate = minSize; |
||
303 | currDoc->maxCanvasCoordinate = maxSize; |
||
68 | Franz | 304 | dr->setPixmap(loadIcon("DragPix.xpm")); |
305 | dr->drag(); |
||
306 | delete ss; |
||
3292 | cbradney | 307 | currDoc->DragP = false; |
308 | currDoc->DraggedElem = 0; |
||
309 | currDoc->DragElements.clear(); |
||
217 | Franz | 310 | } |
68 | Franz | 311 | else |
357 | Franz | 312 | { |
3292 | cbradney | 313 | currDoc->setModified(false); |
3207 | craig | 314 | ScApp->slotDocCh(); |
357 | Franz | 315 | } |
68 | Franz | 316 | } |
317 | |||
202 | Franz | 318 | /*! |
319 | \fn void SVGPlug::addGraphicContext() |
||
320 | \author Franz Schmid |
||
321 | \date |
||
322 | \brief |
||
323 | \param None |
||
324 | \retval None |
||
325 | */ |
||
68 | Franz | 326 | void SVGPlug::addGraphicContext() |
327 | { |
||
328 | SvgStyle *gc = new SvgStyle; |
||
329 | if ( m_gc.current() ) |
||
330 | *gc = *( m_gc.current() ); |
||
331 | m_gc.push( gc ); |
||
332 | } |
||
333 | |||
202 | Franz | 334 | /*! |
335 | \fn void SVGPlug::setupTransform( const QDomElement &e ) |
||
336 | \author Franz Schmid |
||
337 | \date |
||
338 | \brief |
||
339 | \param e const QDomElement & |
||
340 | \retval None |
||
341 | */ |
||
68 | Franz | 342 | void SVGPlug::setupTransform( const QDomElement &e ) |
343 | { |
||
344 | SvgStyle *gc = m_gc.current(); |
||
345 | QWMatrix mat = parseTransform( e.attribute( "transform" ) ); |
||
346 | if (!e.attribute("transform").isEmpty()) |
||
347 | gc->matrix = mat * gc->matrix; |
||
348 | } |
||
349 | |||
202 | Franz | 350 | /*! |
351 | \fn void SVGPlug::parseGroup(const QDomElement &e) |
||
352 | \author Franz Schmid |
||
353 | \date |
||
354 | \brief |
||
355 | \param e const QDomElement & |
||
356 | \retval None |
||
357 | */ |
||
991 | fschmid | 358 | QPtrList<PageItem> SVGPlug::parseGroup(const QDomElement &e) |
68 | Franz | 359 | { |
360 | QPtrList<PageItem> GElements; |
||
361 | FPointArray ImgClip; |
||
362 | ImgClip.resize(0); |
||
3292 | cbradney | 363 | double BaseX = currDoc->currentPage->xOffset(); |
364 | double BaseY = currDoc->currentPage->yOffset(); |
||
68 | Franz | 365 | for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() ) |
217 | Franz | 366 | { |
68 | Franz | 367 | int z = -1; |
368 | QDomElement b = n.toElement(); |
||
369 | if( b.isNull() ) |
||
370 | continue; |
||
371 | QString STag = b.tagName(); |
||
372 | if( STag == "g" ) |
||
217 | Franz | 373 | { |
68 | Franz | 374 | addGraphicContext(); |
375 | SvgStyle *gc = m_gc.current(); |
||
376 | setupTransform( b ); |
||
377 | parseStyle( gc, b ); |
||
991 | fschmid | 378 | QPtrList<PageItem> gElements = parseGroup( b ); |
379 | for (uint gr = 0; gr < gElements.count(); ++gr) |
||
217 | Franz | 380 | { |
3292 | cbradney | 381 | gElements.at(gr)->Groups.push(currDoc->GroupCounter); |
991 | fschmid | 382 | GElements.append(gElements.at(gr)); |
217 | Franz | 383 | } |
68 | Franz | 384 | delete( m_gc.pop() ); |
3292 | cbradney | 385 | currDoc->GroupCounter++; |
68 | Franz | 386 | continue; |
217 | Franz | 387 | } |
68 | Franz | 388 | if( b.tagName() == "defs" ) |
217 | Franz | 389 | { |
68 | Franz | 390 | parseGroup( b ); // try for gradients at least |
391 | continue; |
||
217 | Franz | 392 | } |
68 | Franz | 393 | else if( STag == "linearGradient" || STag == "radialGradient" ) |
217 | Franz | 394 | { |
68 | Franz | 395 | parseGradient( b ); |
396 | continue; |
||
217 | Franz | 397 | } |
68 | Franz | 398 | else if( STag == "rect" ) |
217 | Franz | 399 | { |
68 | Franz | 400 | addGraphicContext(); |
3292 | cbradney | 401 | double x = parseUnit( b.attribute( "x" ) ); |
402 | double y = parseUnit( b.attribute( "y" ) ); |
||
456 | fschmid | 403 | double width = parseUnit( b.attribute( "width" )); |
404 | double height = parseUnit( b.attribute( "height" ) ); |
||
68 | Franz | 405 | double rx = b.attribute( "rx" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "rx" ) ); |
406 | double ry = b.attribute( "ry" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "ry" ) ); |
||
407 | SvgStyle *gc = m_gc.current(); |
||
408 | parseStyle( gc, b ); |
||
3292 | cbradney | 409 | //z = ScApp->view->PaintRect(BaseX, BaseY, width, height, gc->LWidth, gc->FillCol, gc->StrokeCol); |
410 | z = currDoc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
411 | PageItem* ite = currDoc->Items.at(z); |
||
68 | Franz | 412 | if ((rx != 0) || (ry != 0)) |
217 | Franz | 413 | { |
68 | Franz | 414 | ite->RadRect = QMAX(rx, ry); |
3242 | cbradney | 415 | ite->SetFrameRound(); |
416 | ScApp->view->setRedrawBounding(ite); |
||
217 | Franz | 417 | } |
68 | Franz | 418 | QWMatrix mm = QWMatrix(); |
419 | mm.translate(x, y); |
||
420 | ite->PoLine.map(mm); |
||
1065 | cbradney | 421 | FPoint wh = getMaxClipF(&ite->PoLine); |
95 | Franz | 422 | ite->Width = wh.x(); |
423 | ite->Height = wh.y(); |
||
217 | Franz | 424 | } |
68 | Franz | 425 | else if( STag == "ellipse" ) |
217 | Franz | 426 | { |
68 | Franz | 427 | addGraphicContext(); |
456 | fschmid | 428 | double rx = parseUnit( b.attribute( "rx" ) ); |
429 | double ry = parseUnit( b.attribute( "ry" ) ); |
||
430 | double x = parseUnit( b.attribute( "cx" ) ) - rx; |
||
431 | double y = parseUnit( b.attribute( "cy" ) ) - ry; |
||
68 | Franz | 432 | SvgStyle *gc = m_gc.current(); |
433 | parseStyle( gc, b ); |
||
3292 | cbradney | 434 | //z = ScApp->view->PaintEllipse(BaseX, BaseY, rx * 2.0, ry * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol); |
435 | z = currDoc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, rx * 2.0, ry * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
436 | PageItem* ite = currDoc->Items.at(z); |
||
68 | Franz | 437 | QWMatrix mm = QWMatrix(); |
438 | mm.translate(x, y); |
||
439 | ite->PoLine.map(mm); |
||
1065 | cbradney | 440 | FPoint wh = getMaxClipF(&ite->PoLine); |
95 | Franz | 441 | ite->Width = wh.x(); |
442 | ite->Height = wh.y(); |
||
217 | Franz | 443 | } |
68 | Franz | 444 | else if( STag == "circle" ) |
217 | Franz | 445 | { |
68 | Franz | 446 | addGraphicContext(); |
3292 | cbradney | 447 | double r = parseUnit( b.attribute( "r" ) ); |
448 | double x = parseUnit( b.attribute( "cx" ) ) - r; |
||
449 | double y = parseUnit( b.attribute( "cy" ) ) - r; |
||
68 | Franz | 450 | SvgStyle *gc = m_gc.current(); |
451 | parseStyle( gc, b ); |
||
3292 | cbradney | 452 | //z = ScApp->view->PaintEllipse(BaseX, BaseY, r * 2.0, r * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol); |
453 | z = currDoc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, r * 2.0, r * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
454 | PageItem* ite = currDoc->Items.at(z); |
||
68 | Franz | 455 | QWMatrix mm = QWMatrix(); |
456 | mm.translate(x, y); |
||
457 | ite->PoLine.map(mm); |
||
1065 | cbradney | 458 | FPoint wh = getMaxClipF(&ite->PoLine); |
95 | Franz | 459 | ite->Width = wh.x(); |
460 | ite->Height = wh.y(); |
||
217 | Franz | 461 | } |
68 | Franz | 462 | else if( STag == "line" ) |
217 | Franz | 463 | { |
68 | Franz | 464 | addGraphicContext(); |
465 | double x1 = b.attribute( "x1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x1" ) ); |
||
466 | double y1 = b.attribute( "y1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y1" ) ); |
||
467 | double x2 = b.attribute( "x2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x2" ) ); |
||
468 | double y2 = b.attribute( "y2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y2" ) ); |
||
469 | SvgStyle *gc = m_gc.current(); |
||
470 | parseStyle( gc, b ); |
||
3292 | cbradney | 471 | //z = ScApp->view->PaintPoly(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol); |
472 | z = currDoc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
473 | PageItem* ite = currDoc->Items.at(z); |
||
68 | Franz | 474 | ite->PoLine.resize(4); |
475 | ite->PoLine.setPoint(0, FPoint(x1, y1)); |
||
476 | ite->PoLine.setPoint(1, FPoint(x1, y1)); |
||
477 | ite->PoLine.setPoint(2, FPoint(x2, y2)); |
||
478 | ite->PoLine.setPoint(3, FPoint(x2, y2)); |
||
217 | Franz | 479 | } |
68 | Franz | 480 | else if( STag == "clipPath" ) |
217 | Franz | 481 | { |
68 | Franz | 482 | QDomNode n2 = b.firstChild(); |
483 | QDomElement b2 = n2.toElement(); |
||
484 | parseSVG( b2.attribute( "d" ), &ImgClip ); |
||
485 | continue; |
||
217 | Franz | 486 | } |
68 | Franz | 487 | else if( STag == "path" ) |
217 | Franz | 488 | { |
68 | Franz | 489 | addGraphicContext(); |
490 | SvgStyle *gc = m_gc.current(); |
||
491 | parseStyle( gc, b ); |
||
3292 | cbradney | 492 | //z = ScApp->view->PaintPoly(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol); |
493 | z = currDoc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
494 | PageItem* ite = currDoc->Items.at(z); |
||
68 | Franz | 495 | ite->PoLine.resize(0); |
496 | if (parseSVG( b.attribute( "d" ), &ite->PoLine )) |
||
1460 | cbradney | 497 | ite->convertTo(PageItem::PolyLine); |
68 | Franz | 498 | if (ite->PoLine.size() < 4) |
217 | Franz | 499 | { |
3207 | craig | 500 | ScApp->view->SelItem.append(ite); |
501 | ScApp->view->DeleteItem(); |
||
68 | Franz | 502 | z = -1; |
503 | } |
||
217 | Franz | 504 | } |
68 | Franz | 505 | else if( STag == "polyline" || b.tagName() == "polygon" ) |
217 | Franz | 506 | { |
68 | Franz | 507 | addGraphicContext(); |
508 | SvgStyle *gc = m_gc.current(); |
||
509 | parseStyle( gc, b ); |
||
510 | if( b.tagName() == "polygon" ) |
||
3292 | cbradney | 511 | //z = ScApp->view->PaintPoly(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol); |
512 | z = currDoc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
68 | Franz | 513 | else |
3292 | cbradney | 514 | //z = ScApp->view->PaintPolyLine(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol); |
515 | z = currDoc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed); |
||
516 | PageItem* ite = currDoc->Items.at(z); |
||
68 | Franz | 517 | ite->PoLine.resize(0); |
518 | bool bFirst = true; |
||
519 | double x = 0.0; |
||
520 | double y = 0.0; |
||
521 | QString points = b.attribute( "points" ).simplifyWhiteSpace(); |
||
522 | points.replace( QRegExp( "," ), " " ); |
||
523 | points.replace( QRegExp( "\r" ), "" ); |
||
217 | Franz | 524 | points.replace( QRegExp( "\n" ), "" ); |
68 | Franz | 525 | QStringList pointList = QStringList::split( ' ', points ); |
526 | FirstM = true; |
||
527 | for( QStringList::Iterator it = pointList.begin(); it != pointList.end(); it++ ) |
||
217 | Franz | 528 | { |
529 | if( bFirst ) |
||
68 | Franz | 530 | { |
531 | x = (*(it++)).toDouble(); |
||
532 | y = (*it).toDouble(); |
||
2597 | fschmid | 533 | svgMoveTo(x * Conversion, y * Conversion); |
68 | Franz | 534 | bFirst = false; |
535 | WasM = true; |
||
217 | Franz | 536 | } |
68 | Franz | 537 | else |
217 | Franz | 538 | { |
68 | Franz | 539 | x = (*(it++)).toDouble(); |
540 | y = (*it).toDouble(); |
||
2597 | fschmid | 541 | svgLineTo(&ite->PoLine, x * Conversion, y * Conversion); |
68 | Franz | 542 | } |
217 | Franz | 543 | } |
68 | Franz | 544 | if( STag == "polygon" ) |
545 | svgClosePath(&ite->PoLine); |
||
546 | else |
||
1460 | cbradney | 547 | ite->convertTo(PageItem::PolyLine); |
217 | Franz | 548 | } |
68 | Franz | 549 | else if( STag == "text" ) |
217 | Franz | 550 | { |
68 | Franz | 551 | addGraphicContext(); |
552 | SvgStyle *gc = m_gc.current(); |
||
553 | double x = b.attribute( "x" ).isEmpty() ? 0.0 : parseUnit(b.attribute("x")); |
||
554 | double y = b.attribute( "y" ).isEmpty() ? 0.0 : parseUnit(b.attribute("y")); |
||
555 | parseStyle(gc, b); |
||
456 | fschmid | 556 | QPtrList<PageItem> el = parseText(x+BaseX, y+BaseY, b); |
215 | Franz | 557 | for (uint ec = 0; ec < el.count(); ++ec) |
558 | { |
||
559 | GElements.append(el.at(ec)); |
||
68 | Franz | 560 | } |
215 | Franz | 561 | z = -1; |
217 | Franz | 562 | } |
68 | Franz | 563 | else if( STag == "image" ) |
217 | Franz | 564 | { |
68 | Franz | 565 | addGraphicContext(); |
566 | QString fname = b.attribute("xlink:href"); |
||
567 | double x = b.attribute( "x" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x" ) ); |
||
568 | double y = b.attribute( "y" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y" ) ); |
||
569 | double w = b.attribute( "width" ).isEmpty() ? 1.0 : parseUnit( b.attribute( "width" ) ); |
||
570 | double h = b.attribute( "height" ).isEmpty() ? 1.0 : parseUnit( b.attribute( "height" ) ); |
||
3292 | cbradney | 571 | //z = ScApp->view->PaintPict(x+BaseX, y+BaseY, w, h); |
572 | z = currDoc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, x+BaseX, y+BaseY, w, h, 1, currDoc->toolSettings.dBrushPict, "None", !ScApp->view->Mpressed); |
||
2877 | cbradney | 573 | if (!fname.isEmpty()) |
3207 | craig | 574 | ScApp->view->LoadPict(fname, z); |
3292 | cbradney | 575 | PageItem* ite = currDoc->Items.at(z); |
68 | Franz | 576 | if (ImgClip.size() != 0) |
577 | ite->PoLine = ImgClip.copy(); |
||
578 | ImgClip.resize(0); |
||
579 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
||
217 | Franz | 580 | } |
68 | Franz | 581 | else |
582 | continue; |
||
583 | if (z != -1) |
||
217 | Franz | 584 | { |
68 | Franz | 585 | setupTransform( b ); |
586 | SvgStyle *gc = m_gc.current(); |
||
3292 | cbradney | 587 | PageItem* ite = currDoc->Items.at(z); |
1460 | cbradney | 588 | switch (ite->itemType()) |
217 | Franz | 589 | { |
1460 | cbradney | 590 | case PageItem::ImageFrame: |
68 | Franz | 591 | { |
592 | QWMatrix mm = gc->matrix; |
||
593 | ite->Xpos += mm.dx(); |
||
594 | ite->Ypos += mm.dy(); |
||
595 | ite->Width = ite->Width * mm.m11(); |
||
596 | ite->Height = ite->Height * mm.m22(); |
||
330 | Franz | 597 | ite->Pwidth = ite->Pwidth * ((mm.m11() + mm.m22()) / 2.0); |
68 | Franz | 598 | if (ite->PicAvail) |
217 | Franz | 599 | { |
68 | Franz | 600 | ite->LocalScX = ite->Width / ite->pixm.width(); |
601 | ite->LocalScY = ite->Height / ite->pixm.height(); |
||
602 | } |
||
603 | break; |
||
217 | Franz | 604 | } |
1460 | cbradney | 605 | case PageItem::TextFrame: |
330 | Franz | 606 | { |
607 | QWMatrix mm = gc->matrix; |
||
608 | ite->Pwidth = ite->Pwidth * ((mm.m11() + mm.m22()) / 2.0); |
||
609 | } |
||
217 | Franz | 610 | break; |
611 | default: |
||
612 | { |
||
68 | Franz | 613 | ite->ClipEdited = true; |
614 | ite->FrameType = 3; |
||
615 | QWMatrix mm = gc->matrix; |
||
616 | ite->PoLine.map(mm); |
||
1013 | fschmid | 617 | if (haveViewBox) |
618 | { |
||
619 | QWMatrix mv; |
||
620 | mv.translate(viewTransformX, viewTransformY); |
||
621 | mv.scale(viewScaleX, viewScaleY); |
||
622 | ite->PoLine.map(mv); |
||
623 | } |
||
330 | Franz | 624 | ite->Pwidth = ite->Pwidth * ((mm.m11() + mm.m22()) / 2.0); |
1065 | cbradney | 625 | FPoint wh = getMaxClipF(&ite->PoLine); |
95 | Franz | 626 | ite->Width = wh.x(); |
627 | ite->Height = wh.y(); |
||
68 | Franz | 628 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
3207 | craig | 629 | ScApp->view->AdjustItemSize(ite); |
68 | Franz | 630 | break; |
631 | } |
||
217 | Franz | 632 | } |
68 | Franz | 633 | if( !b.attribute("id").isEmpty() ) |
1361 | tsoots | 634 | ite->setItemName(" "+b.attribute("id")); |
1394 | cbradney | 635 | ite->setFillTransparency(gc->Transparency); |
636 | ite->setLineTransparency(gc->TranspStroke); |
||
68 | Franz | 637 | ite->PLineEnd = gc->PLineEnd; |
638 | ite->PLineJoin = gc->PLineJoin; |
||
1653 | craig | 639 | ite->setTextFlowsAroundFrame(false); |
68 | Franz | 640 | ite->DashOffset = gc->dashOffset; |
641 | ite->DashValues = gc->dashArray; |
||
642 | if (gc->Gradient != 0) |
||
217 | Franz | 643 | { |
298 | Franz | 644 | ite->fill_gradient = gc->GradCo; |
645 | if (!gc->CSpace) |
||
296 | Franz | 646 | { |
298 | Franz | 647 | ite->GrStartX = gc->GX1 * ite->Width; |
648 | ite->GrStartY = gc->GY1 * ite->Height; |
||
649 | ite->GrEndX = gc->GX2 * ite->Width; |
||
650 | ite->GrEndY = gc->GY2 * ite->Height; |
||
302 | Franz | 651 | double angle1 = atan2(gc->GY2-gc->GY1,gc->GX2-gc->GX1)*(180.0/M_PI); |
652 | double angle2 = atan2(ite->GrEndY-ite->GrStartX,ite->GrEndX-ite->GrStartX)*(180.0/M_PI); |
||
653 | double dx = ite->GrStartX + (ite->GrEndX-ite->GrStartX) / 2.0; |
||
654 | double dy = ite->GrStartY + (ite->GrEndY-ite->GrStartY) / 2.0; |
||
776 | fschmid | 655 | QWMatrix mm, mm2; |
308 | Franz | 656 | if ((gc->GY1 < gc->GY2) && (gc->GX1 < gc->GX2)) |
302 | Franz | 657 | { |
658 | mm.rotate(-angle2); |
||
776 | fschmid | 659 | mm2.rotate(angle1); |
302 | Franz | 660 | } |
661 | FPointArray gra; |
||
662 | gra.setPoints(2, ite->GrStartX-dx, ite->GrStartY-dy, ite->GrEndX-dx, ite->GrEndY-dy); |
||
776 | fschmid | 663 | gra.map(mm*mm2); |
302 | Franz | 664 | gra.translate(dx, dy); |
665 | ite->GrStartX = gra.point(0).x(); |
||
666 | ite->GrStartY = gra.point(0).y(); |
||
667 | ite->GrEndX = gra.point(1).x(); |
||
668 | ite->GrEndY = gra.point(1).y(); |
||
298 | Franz | 669 | } |
670 | else |
||
671 | { |
||
296 | Franz | 672 | QWMatrix mm = gc->matrix; |
302 | Franz | 673 | mm = mm * gc->matrixg; |
296 | Franz | 674 | FPointArray gra; |
675 | gra.setPoints(2, gc->GX1, gc->GY1, gc->GX2, gc->GY2); |
||
676 | gra.map(mm); |
||
677 | gc->GX1 = gra.point(0).x(); |
||
678 | gc->GY1 = gra.point(0).y(); |
||
679 | gc->GX2 = gra.point(1).x(); |
||
680 | gc->GY2 = gra.point(1).y(); |
||
456 | fschmid | 681 | ite->GrStartX = gc->GX1 - ite->Xpos+BaseX; |
682 | ite->GrStartY = gc->GY1 - ite->Ypos+BaseY; |
||
683 | ite->GrEndX = gc->GX2 - ite->Xpos+BaseX; |
||
684 | ite->GrEndY = gc->GY2 - ite->Ypos+BaseY; |
||
298 | Franz | 685 | } |
296 | Franz | 686 | ite->GrType = gc->Gradient; |
217 | Franz | 687 | } |
68 | Franz | 688 | GElements.append(ite); |
689 | Elements.append(ite); |
||
217 | Franz | 690 | } |
68 | Franz | 691 | delete( m_gc.pop() ); |
217 | Franz | 692 | } |
991 | fschmid | 693 | return GElements; |
68 | Franz | 694 | } |
695 | |||
202 | Franz | 696 | /*! |
697 | \fn double SVGPlug::fromPercentage( const QString &s ) |
||
698 | \author Franz Schmid |
||
699 | \date |
||
700 | \brief |
||
701 | \param s const QString & |
||
702 | \retval double |
||
703 | */ |
||
68 | Franz | 704 | double SVGPlug::fromPercentage( const QString &s ) |
705 | { |
||
706 | if( s.endsWith( "%" ) ) |
||
707 | return s.toDouble() / 100.0; |
||
708 | else |
||
709 | return s.toDouble(); |
||
710 | } |
||
711 | |||
202 | Franz | 712 | /*! |
713 | \fn double SVGPlug::parseUnit(const QString &unit) |
||
714 | \author Franz Schmid |
||
715 | \date |
||
716 | \brief |
||
717 | \param unit const QString & |
||
718 | \retval double |
||
719 | */ |
||
68 | Franz | 720 | double SVGPlug::parseUnit(const QString &unit) |
721 | { |
||
693 | fschmid | 722 | bool noUnit = false; |
270 | Franz | 723 | QString unitval=unit; |
724 | if( unit.right( 2 ) == "pt" ) |
||
725 | unitval.replace( "pt", "" ); |
||
726 | else if( unit.right( 2 ) == "cm" ) |
||
727 | unitval.replace( "cm", "" ); |
||
728 | else if( unit.right( 2 ) == "mm" ) |
||
729 | unitval.replace( "mm" , "" ); |
||
730 | else if( unit.right( 2 ) == "in" ) |
||
731 | unitval.replace( "in", "" ); |
||
732 | else if( unit.right( 2 ) == "px" ) |
||
733 | unitval.replace( "px", "" ); |
||
693 | fschmid | 734 | if (unitval == unit) |
735 | noUnit = true; |
||
270 | Franz | 736 | double value = unitval.toDouble(); |
737 | if( unit.right( 2 ) == "pt" ) |
||
738 | value = value; |
||
739 | else if( unit.right( 2 ) == "cm" ) |
||
740 | value = ( value / 2.54 ) * 72; |
||
741 | else if( unit.right( 2 ) == "mm" ) |
||
742 | value = ( value / 25.4 ) * 72; |
||
743 | else if( unit.right( 2 ) == "in" ) |
||
744 | value = value * 72; |
||
745 | else if( unit.right( 2 ) == "px" ) |
||
865 | fschmid | 746 | value = value * 0.8; |
693 | fschmid | 747 | else if(noUnit) |
976 | fschmid | 748 | value = value * Conversion; |
68 | Franz | 749 | return value; |
750 | } |
||
751 | |||
202 | Franz | 752 | /*! |
753 | \fn QWMatrix SVGPlug::parseTransform( const QString &transform ) |
||
754 | \author Franz Schmid |
||
755 | \date |
||
756 | \brief |
||
757 | \param transform const QString |
||
758 | \retval QWMatrix |
||
759 | */ |
||
68 | Franz | 760 | QWMatrix SVGPlug::parseTransform( const QString &transform ) |
761 | { |
||
2597 | fschmid | 762 | QWMatrix ret; |
68 | Franz | 763 | // Split string for handling 1 transform statement at a time |
764 | QStringList subtransforms = QStringList::split(')', transform); |
||
765 | QStringList::ConstIterator it = subtransforms.begin(); |
||
766 | QStringList::ConstIterator end = subtransforms.end(); |
||
767 | for(; it != end; ++it) |
||
768 | { |
||
2597 | fschmid | 769 | QWMatrix result; |
68 | Franz | 770 | QStringList subtransform = QStringList::split('(', (*it)); |
771 | subtransform[0] = subtransform[0].stripWhiteSpace().lower(); |
||
772 | subtransform[1] = subtransform[1].simplifyWhiteSpace(); |
||
773 | QRegExp reg("[,( ]"); |
||
774 | QStringList params = QStringList::split(reg, subtransform[1]); |
||
775 | if(subtransform[0].startsWith(";") || subtransform[0].startsWith(",")) |
||
776 | subtransform[0] = subtransform[0].right(subtransform[0].length() - 1); |
||
777 | if(subtransform[0] == "rotate") |
||
778 | { |
||
779 | if(params.count() == 3) |
||
780 | { |
||
976 | fschmid | 781 | double x = params[1].toDouble() * Conversion; |
782 | double y = params[2].toDouble() * Conversion; |
||
68 | Franz | 783 | result.translate(x, y); |
784 | result.rotate(params[0].toDouble()); |
||
785 | result.translate(-x, -y); |
||
786 | } |
||
787 | else |
||
788 | result.rotate(params[0].toDouble()); |
||
789 | } |
||
790 | else if(subtransform[0] == "translate") |
||
791 | { |
||
792 | if(params.count() == 2) |
||
976 | fschmid | 793 | result.translate(params[0].toDouble() * Conversion, params[1].toDouble() * Conversion); |
68 | Franz | 794 | else // Spec : if only one param given, assume 2nd param to be 0 |
2597 | fschmid | 795 | result.translate(params[0].toDouble() * Conversion, 0); |
68 | Franz | 796 | } |
797 | else if(subtransform[0] == "scale") |
||
798 | { |
||
799 | if(params.count() == 2) |
||
800 | result.scale(params[0].toDouble(), params[1].toDouble()); |
||
801 | else // Spec : if only one param given, assume uniform scaling |
||
802 | result.scale(params[0].toDouble(), params[0].toDouble()); |
||
803 | } |
||
804 | else if(subtransform[0] == "skewx") |
||
805 | result.shear(tan(params[0].toDouble() * 0.01745329251994329576), 0.0F); |
||
806 | else if(subtransform[0] == "skewy") |
||
807 | result.shear(0.0F, tan(params[0].toDouble() * 0.01745329251994329576)); |
||
808 | else if(subtransform[0] == "matrix") |
||
809 | { |
||
810 | if(params.count() >= 6) |
||
332 | Franz | 811 | { |
812 | double sx = params[0].toDouble(); |
||
813 | double sy = params[3].toDouble(); |
||
976 | fschmid | 814 | result.setMatrix(sx, params[1].toDouble(), params[2].toDouble(), sy, params[4].toDouble() * Conversion, params[5].toDouble() * Conversion); |
332 | Franz | 815 | } |
68 | Franz | 816 | } |
2597 | fschmid | 817 | ret = ret * result; |
68 | Franz | 818 | } |
2597 | fschmid | 819 | return ret; |
68 | Franz | 820 | } |
821 | |||
202 | Franz | 822 | /*! |
823 | \fn const char * SVGPlug::getCoord( const char *ptr, double &number ) |
||
824 | \author Franz Schmid |
||
825 | \date |
||
826 | \brief |
||
827 | \param ptr const char * |
||
828 | \param number double & |
||
829 | \retval const char * |
||
830 | */ |
||
68 | Franz | 831 | const char * SVGPlug::getCoord( const char *ptr, double &number ) |
832 | { |
||
833 | int integer, exponent; |
||
834 | double decimal, frac; |
||
835 | int sign, expsign; |
||
836 | |||
837 | exponent = 0; |
||
838 | integer = 0; |
||
839 | frac = 1.0; |
||
840 | decimal = 0; |
||
841 | sign = 1; |
||
842 | expsign = 1; |
||
843 | |||
844 | // read the sign |
||
845 | if(*ptr == '+') |
||
846 | ptr++; |
||
847 | else if(*ptr == '-') |
||
848 | { |
||
849 | ptr++; |
||
850 | sign = -1; |
||
851 | } |
||
852 | |||
853 | // read the integer part |
||
854 | while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') |
||
855 | integer = (integer * 10) + *(ptr++) - '0'; |
||
856 | if(*ptr == '.') // read the decimals |
||
217 | Franz | 857 | { |
68 | Franz | 858 | ptr++; |
859 | while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') |
||
860 | decimal += (*(ptr++) - '0') * (frac *= 0.1); |
||
217 | Franz | 861 | } |
68 | Franz | 862 | |
863 | if(*ptr == 'e' || *ptr == 'E') // read the exponent part |
||
864 | { |
||
865 | ptr++; |
||
866 | |||
867 | // read the sign of the exponent |
||
868 | if(*ptr == '+') |
||
869 | ptr++; |
||
870 | else if(*ptr == '-') |
||
871 | { |
||
872 | ptr++; |
||
873 | expsign = -1; |
||
874 | } |
||
875 | |||
876 | exponent = 0; |
||
877 | while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') |
||
878 | { |
||
879 | exponent *= 10; |
||
880 | exponent += *ptr - '0'; |
||
881 | ptr++; |
||
882 | } |
||
217 | Franz | 883 | } |
68 | Franz | 884 | number = integer + decimal; |
80 | Franz | 885 | number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) ); |
68 | Franz | 886 | // skip the following space |
887 | if(*ptr == ' ') |
||
888 | ptr++; |
||
889 | |||
890 | return ptr; |
||
891 | } |
||
892 | |||
202 | Franz | 893 | /*! |
894 | \fn bool SVGPlug::parseSVG( const QString &s, FPointArray *ite ) |
||
895 | \author Franz Schmid |
||
896 | \date |
||
897 | \brief |
||
898 | \param s const QString & |
||
899 | \param ite FPointArray * |
||
900 | \retval bool |
||
901 | */ |
||
68 | Franz | 902 | bool SVGPlug::parseSVG( const QString &s, FPointArray *ite ) |
903 | { |
||
904 | QString d = s; |
||
905 | d = d.replace( QRegExp( "," ), " "); |
||
906 | bool ret = false; |
||
907 | if( !d.isEmpty() ) |
||
217 | Franz | 908 | { |
68 | Franz | 909 | d = d.simplifyWhiteSpace(); |
910 | const char *ptr = d.latin1(); |
||
911 | const char *end = d.latin1() + d.length() + 1; |
||
912 | double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc; |
||
913 | double px1, py1, px2, py2, px3, py3; |
||
914 | bool relative; |
||
915 | FirstM = true; |
||
916 | char command = *(ptr++), lastCommand = ' '; |
||
917 | subpathx = subpathy = curx = cury = contrlx = contrly = 0.0; |
||
918 | while( ptr < end ) |
||
217 | Franz | 919 | { |
68 | Franz | 920 | if( *ptr == ' ' ) |
921 | ptr++; |
||
922 | relative = false; |
||
923 | switch( command ) |
||
924 | { |
||
217 | Franz | 925 | case 'm': |
926 | relative = true; |
||
927 | case 'M': |
||
928 | { |
||
68 | Franz | 929 | ptr = getCoord( ptr, tox ); |
930 | ptr = getCoord( ptr, toy ); |
||
976 | fschmid | 931 | tox *= Conversion; |
932 | toy *= Conversion; |
||
68 | Franz | 933 | WasM = true; |
934 | subpathx = curx = relative ? curx + tox : tox; |
||
935 | subpathy = cury = relative ? cury + toy : toy; |
||
456 | fschmid | 936 | svgMoveTo(curx, cury ); |
68 | Franz | 937 | break; |
217 | Franz | 938 | } |
939 | case 'l': |
||
940 | relative = true; |
||
941 | case 'L': |
||
942 | { |
||
68 | Franz | 943 | ptr = getCoord( ptr, tox ); |
944 | ptr = getCoord( ptr, toy ); |
||
976 | fschmid | 945 | tox *= Conversion; |
946 | toy *= Conversion; |
||
68 | Franz | 947 | curx = relative ? curx + tox : tox; |
948 | cury = relative ? cury + toy : toy; |
||
949 | svgLineTo(ite, curx, cury ); |
||
950 | break; |
||
217 | Franz | 951 | } |
952 | case 'h': |
||
953 | { |
||
68 | Franz | 954 | ptr = getCoord( ptr, tox ); |
976 | fschmid | 955 | tox *= Conversion; |
68 | Franz | 956 | curx = curx + tox; |
957 | svgLineTo(ite, curx, cury ); |
||
958 | break; |
||
217 | Franz | 959 | } |
960 | case 'H': |
||
961 | { |
||
68 | Franz | 962 | ptr = getCoord( ptr, tox ); |
976 | fschmid | 963 | tox *= Conversion; |
68 | Franz | 964 | curx = tox; |
965 | svgLineTo(ite, curx, cury ); |
||
966 | break; |
||
217 | Franz | 967 | } |
968 | case 'v': |
||
969 | { |
||
68 | Franz | 970 | ptr = getCoord( ptr, toy ); |
976 | fschmid | 971 | toy *= Conversion; |
68 | Franz | 972 | cury = cury + toy; |
973 | svgLineTo(ite, curx, cury ); |
||
974 | break; |
||
217 | Franz | 975 | } |
976 | case 'V': |
||
977 | { |
||
68 | Franz | 978 | ptr = getCoord( ptr, toy ); |
976 | fschmid | 979 | toy *= Conversion; |
68 | Franz | 980 | cury = toy; |
981 | svgLineTo(ite, curx, cury ); |
||
982 | break; |
||
217 | Franz | 983 | } |
984 | case 'z': |
||
985 | case 'Z': |
||
986 | { |
||
68 | Franz | 987 | curx = subpathx; |
988 | cury = subpathy; |
||
989 | svgClosePath(ite); |
||
990 | break; |
||
217 | Franz | 991 | } |
992 | case 'c': |
||
993 | relative = true; |
||
994 | case 'C': |
||
995 | { |
||
68 | Franz | 996 | ptr = getCoord( ptr, x1 ); |
997 | ptr = getCoord( ptr, y1 ); |
||
998 | ptr = getCoord( ptr, x2 ); |
||
999 | ptr = getCoord( ptr, y2 ); |
||
1000 | ptr = getCoord( ptr, tox ); |
||
1001 | ptr = getCoord( ptr, toy ); |
||
976 | fschmid | 1002 | tox *= Conversion; |
1003 | toy *= Conversion; |
||
1004 | x1 *= Conversion; |
||
1005 | y1 *= Conversion; |
||
1006 | x2 *= Conversion; |
||
1007 | y2 *= Conversion; |
||
68 | Franz | 1008 | px1 = relative ? curx + x1 : x1; |
1009 | py1 = relative ? cury + y1 : y1; |
||
1010 | px2 = relative ? curx + x2 : x2; |
||
1011 | py2 = relative ? cury + y2 : y2; |
||
1012 | px3 = relative ? curx + tox : tox; |
||
1013 | py3 = relative ? cury + toy : toy; |
||
217 | Franz | 1014 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
1015 | contrlx = relative ? curx + x2 : x2; |
||
68 | Franz | 1016 | contrly = relative ? cury + y2 : y2; |
1017 | curx = relative ? curx + tox : tox; |
||
1018 | cury = relative ? cury + toy : toy; |
||
1019 | break; |
||
217 | Franz | 1020 | } |
1021 | case 's': |
||
1022 | relative = true; |
||
1023 | case 'S': |
||
1024 | { |
||
68 | Franz | 1025 | ptr = getCoord( ptr, x2 ); |
1026 | ptr = getCoord( ptr, y2 ); |
||
1027 | ptr = getCoord( ptr, tox ); |
||
1028 | ptr = getCoord( ptr, toy ); |
||
976 | fschmid | 1029 | tox *= Conversion; |
1030 | toy *= Conversion; |
||
1031 | x2 *= Conversion; |
||
1032 | y2 *= Conversion; |
||
68 | Franz | 1033 | px1 = 2 * curx - contrlx; |
1034 | py1 = 2 * cury - contrly; |
||
1035 | px2 = relative ? curx + x2 : x2; |
||
1036 | py2 = relative ? cury + y2 : y2; |
||
1037 | px3 = relative ? curx + tox : tox; |
||
1038 | py3 = relative ? cury + toy : toy; |
||
1039 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1040 | contrlx = relative ? curx + x2 : x2; |
||
1041 | contrly = relative ? cury + y2 : y2; |
||
1042 | curx = relative ? curx + tox : tox; |
||
1043 | cury = relative ? cury + toy : toy; |
||
1044 | break; |
||
217 | Franz | 1045 | } |
1046 | case 'q': |
||
1047 | relative = true; |
||
1048 | case 'Q': |
||
1049 | { |
||
68 | Franz | 1050 | ptr = getCoord( ptr, x1 ); |
1051 | ptr = getCoord( ptr, y1 ); |
||
1052 | ptr = getCoord( ptr, tox ); |
||
1053 | ptr = getCoord( ptr, toy ); |
||
976 | fschmid | 1054 | tox *= Conversion; |
1055 | toy *= Conversion; |
||
1056 | x1 *= Conversion; |
||
1057 | y1 *= Conversion; |
||
68 | Franz | 1058 | px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0); |
1059 | py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0); |
||
1060 | px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0); |
||
1061 | py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0); |
||
1062 | px3 = relative ? curx + tox : tox; |
||
1063 | py3 = relative ? cury + toy : toy; |
||
1064 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1065 | contrlx = relative ? curx + x1 : (tox + 2 * x1) * (1.0 / 3.0); |
||
1066 | contrly = relative ? cury + y1 : (toy + 2 * y1) * (1.0 / 3.0); |
||
1067 | curx = relative ? curx + tox : tox; |
||
1068 | cury = relative ? cury + toy : toy; |
||
1069 | break; |
||
217 | Franz | 1070 | } |
1071 | case 't': |
||
1072 | relative = true; |
||
1073 | case 'T': |
||
1074 | { |
||
68 | Franz | 1075 | ptr = getCoord(ptr, tox); |
1076 | ptr = getCoord(ptr, toy); |
||
976 | fschmid | 1077 | tox *= Conversion; |
1078 | toy *= Conversion; |
||
68 | Franz | 1079 | xc = 2 * curx - contrlx; |
1080 | yc = 2 * cury - contrly; |
||
1081 | px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0); |
||
1082 | py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0); |
||
1083 | px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0); |
||
1084 | py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0); |
||
1085 | px3 = relative ? curx + tox : tox; |
||
1086 | py3 = relative ? cury + toy : toy; |
||
1087 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1088 | contrlx = xc; |
||
1089 | contrly = yc; |
||
1090 | curx = relative ? curx + tox : tox; |
||
1091 | cury = relative ? cury + toy : toy; |
||
1092 | break; |
||
217 | Franz | 1093 | } |
1094 | case 'a': |
||
1095 | relative = true; |
||
1096 | case 'A': |
||
1097 | { |
||
68 | Franz | 1098 | bool largeArc, sweep; |
1099 | double angle, rx, ry; |
||
1100 | ptr = getCoord( ptr, rx ); |
||
1101 | ptr = getCoord( ptr, ry ); |
||
1102 | ptr = getCoord( ptr, angle ); |
||
1103 | ptr = getCoord( ptr, tox ); |
||
976 | fschmid | 1104 | ry *= Conversion; |
1105 | rx *= Conversion; |
||
68 | Franz | 1106 | largeArc = tox == 1; |
1107 | ptr = getCoord( ptr, tox ); |
||
1108 | sweep = tox == 1; |
||
1109 | ptr = getCoord( ptr, tox ); |
||
1110 | ptr = getCoord( ptr, toy ); |
||
976 | fschmid | 1111 | tox *= Conversion; |
1112 | toy *= Conversion; |
||
68 | Franz | 1113 | calculateArc(ite, relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep ); |
1114 | } |
||
217 | Franz | 1115 | } |
68 | Franz | 1116 | lastCommand = command; |
1117 | if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) |
||
217 | Franz | 1118 | { |
68 | Franz | 1119 | // there are still coords in this command |
1120 | if(command == 'M') |
||
1121 | command = 'L'; |
||
1122 | else if(command == 'm') |
||
1123 | command = 'l'; |
||
217 | Franz | 1124 | } |
68 | Franz | 1125 | else |
1126 | command = *(ptr++); |
||
1127 | |||
1128 | if( lastCommand != 'C' && lastCommand != 'c' && |
||
217 | Franz | 1129 | lastCommand != 'S' && lastCommand != 's' && |
1130 | lastCommand != 'Q' && lastCommand != 'q' && |
||
1131 | lastCommand != 'T' && lastCommand != 't') |
||
68 | Franz | 1132 | { |
1133 | contrlx = curx; |
||
1134 | contrly = cury; |
||
1135 | } |
||
1136 | } |
||
1137 | if ((lastCommand != 'z') && (lastCommand != 'Z')) |
||
1138 | ret = true; |
||
1139 | if (ite->size() > 2) |
||
217 | Franz | 1140 | { |
68 | Franz | 1141 | if ((ite->point(0).x() == ite->point(ite->size()-2).x()) && (ite->point(0).y() == ite->point(ite->size()-2).y())) |
1142 | ret = false; |
||
217 | Franz | 1143 | } |
68 | Franz | 1144 | } |
1145 | return ret; |
||
1146 | } |
||
1147 | |||
202 | Franz | 1148 | /*! |
1149 | \fn void SVGPlug::calculateArc(FPointArray *ite, bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag) |
||
1150 | \author Franz Schmid |
||
1151 | \date |
||
1152 | \brief |
||
1153 | \param ite FPointArray * |
||
1154 | \param relative bool |
||
1155 | \param curx double & |
||
1156 | \param cury double & |
||
1157 | \param angle double |
||
1158 | \param x double |
||
1159 | \param y double |
||
1160 | \param r1 double |
||
1161 | \param r2 double |
||
1162 | \param largeArcFlag bool |
||
1163 | \param sweepFlag bool |
||
1164 | \retval None |
||
1165 | */ |
||
68 | Franz | 1166 | void SVGPlug::calculateArc(FPointArray *ite, bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag) |
1167 | { |
||
1168 | double sin_th, cos_th; |
||
1169 | double a00, a01, a10, a11; |
||
1170 | double x0, y0, x1, y1, xc, yc; |
||
1171 | double d, sfactor, sfactor_sq; |
||
1172 | double th0, th1, th_arc; |
||
1173 | int i, n_segs; |
||
1174 | sin_th = sin(angle * (M_PI / 180.0)); |
||
1175 | cos_th = cos(angle * (M_PI / 180.0)); |
||
1176 | double dx; |
||
1177 | if(!relative) |
||
1178 | dx = (curx - x) / 2.0; |
||
1179 | else |
||
1180 | dx = -x / 2.0; |
||
1181 | double dy; |
||
1182 | if(!relative) |
||
1183 | dy = (cury - y) / 2.0; |
||
1184 | else |
||
1185 | dy = -y / 2.0; |
||
1186 | double _x1 = cos_th * dx + sin_th * dy; |
||
1187 | double _y1 = -sin_th * dx + cos_th * dy; |
||
1188 | double Pr1 = r1 * r1; |
||
1189 | double Pr2 = r2 * r2; |
||
1190 | double Px = _x1 * _x1; |
||
1191 | double Py = _y1 * _y1; |
||
1192 | // Spec : check if radii are large enough |
||
1193 | double check = Px / Pr1 + Py / Pr2; |
||
1194 | if(check > 1) |
||
1195 | { |
||
1196 | r1 = r1 * sqrt(check); |
||
1197 | r2 = r2 * sqrt(check); |
||
1198 | } |
||
1199 | a00 = cos_th / r1; |
||
1200 | a01 = sin_th / r1; |
||
1201 | a10 = -sin_th / r2; |
||
1202 | a11 = cos_th / r2; |
||
1203 | x0 = a00 * curx + a01 * cury; |
||
1204 | y0 = a10 * curx + a11 * cury; |
||
1205 | if(!relative) |
||
1206 | x1 = a00 * x + a01 * y; |
||
1207 | else |
||
1208 | x1 = a00 * (curx + x) + a01 * (cury + y); |
||
1209 | if(!relative) |
||
1210 | y1 = a10 * x + a11 * y; |
||
1211 | else |
||
1212 | y1 = a10 * (curx + x) + a11 * (cury + y); |
||
1213 | /* (x0, y0) is current point in transformed coordinate space. |
||
1214 | (x1, y1) is new point in transformed coordinate space. |
||
1215 | |||
1216 | The arc fits a unit-radius circle in this space. |
||
217 | Franz | 1217 | */ |
68 | Franz | 1218 | d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); |
1219 | sfactor_sq = 1.0 / d - 0.25; |
||
1220 | if(sfactor_sq < 0) |
||
1221 | sfactor_sq = 0; |
||
1222 | sfactor = sqrt(sfactor_sq); |
||
1223 | if(sweepFlag == largeArcFlag) |
||
1224 | sfactor = -sfactor; |
||
1225 | xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); |
||
1226 | yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); |
||
1227 | |||
1228 | /* (xc, yc) is center of the circle. */ |
||
1229 | th0 = atan2(y0 - yc, x0 - xc); |
||
1230 | th1 = atan2(y1 - yc, x1 - xc); |
||
1231 | th_arc = th1 - th0; |
||
1232 | if(th_arc < 0 && sweepFlag) |
||
1233 | th_arc += 2 * M_PI; |
||
1234 | else if(th_arc > 0 && !sweepFlag) |
||
1235 | th_arc -= 2 * M_PI; |
||
80 | Franz | 1236 | n_segs = static_cast<int>(ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)))); |
68 | Franz | 1237 | for(i = 0; i < n_segs; i++) |
1238 | { |
||
1239 | { |
||
1240 | double sin_th, cos_th; |
||
1241 | double a00, a01, a10, a11; |
||
1242 | double x1, y1, x2, y2, x3, y3; |
||
1243 | double t; |
||
1244 | double th_half; |
||
1245 | double _th0 = th0 + i * th_arc / n_segs; |
||
1246 | double _th1 = th0 + (i + 1) * th_arc / n_segs; |
||
1247 | sin_th = sin(angle * (M_PI / 180.0)); |
||
1248 | cos_th = cos(angle * (M_PI / 180.0)); |
||
1249 | /* inverse transform compared with rsvg_path_arc */ |
||
1250 | a00 = cos_th * r1; |
||
1251 | a01 = -sin_th * r2; |
||
1252 | a10 = sin_th * r1; |
||
1253 | a11 = cos_th * r2; |
||
1254 | th_half = 0.5 * (_th1 - _th0); |
||
1255 | t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half); |
||
1256 | x1 = xc + cos(_th0) - t * sin(_th0); |
||
1257 | y1 = yc + sin(_th0) + t * cos(_th0); |
||
1258 | x3 = xc + cos(_th1); |
||
1259 | y3 = yc + sin(_th1); |
||
1260 | x2 = x3 + t * sin(_th1); |
||
1261 | y2 = y3 - t * cos(_th1); |
||
1262 | 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 ); |
||
1263 | } |
||
1264 | } |
||
1265 | if(!relative) |
||
1266 | curx = x; |
||
1267 | else |
||
1268 | curx += x; |
||
1269 | if(!relative) |
||
1270 | cury = y; |
||
1271 | else |
||
1272 | cury += y; |
||
1273 | } |
||
1274 | |||
202 | Franz | 1275 | /*! |
1227 | cbradney | 1276 | \fn void SVGPlug::svgMoveTo(double x1, double y1) |
202 | Franz | 1277 | \author Franz Schmid |
1278 | \date |
||
1279 | \brief |
||
1280 | \param i FPointArray * |
||
1281 | \param x1 double |
||
1282 | \param y1 double |
||
1283 | \retval None |
||
1284 | */ |
||
456 | fschmid | 1285 | void SVGPlug::svgMoveTo(double x1, double y1) |
68 | Franz | 1286 | { |
1287 | CurrX = x1; |
||
1288 | CurrY = y1; |
||
1289 | StartX = x1; |
||
1290 | StartY = y1; |
||
1291 | PathLen = 0; |
||
1292 | } |
||
1293 | |||
202 | Franz | 1294 | /*! |
1295 | \fn void SVGPlug::svgLineTo(FPointArray *i, double x1, double y1) |
||
1296 | \author Franz Schmid |
||
1297 | \date |
||
1298 | \brief |
||
1299 | \param i FPointArray * |
||
1300 | \param x1 double |
||
1301 | \param y1 double |
||
1302 | \retval None |
||
1303 | */ |
||
68 | Franz | 1304 | void SVGPlug::svgLineTo(FPointArray *i, double x1, double y1) |
1305 | { |
||
1306 | if ((!FirstM) && (WasM)) |
||
217 | Franz | 1307 | { |
68 | Franz | 1308 | i->setMarker(); |
1309 | PathLen += 4; |
||
217 | Franz | 1310 | } |
68 | Franz | 1311 | FirstM = false; |
1312 | WasM = false; |
||
87 | Franz | 1313 | if (i->size() > 3) |
217 | Franz | 1314 | { |
87 | Franz | 1315 | FPoint b1 = i->point(i->size()-4); |
1316 | FPoint b2 = i->point(i->size()-3); |
||
1317 | FPoint b3 = i->point(i->size()-2); |
||
1318 | FPoint b4 = i->point(i->size()-1); |
||
1319 | FPoint n1 = FPoint(CurrX, CurrY); |
||
1320 | FPoint n2 = FPoint(x1, y1); |
||
1321 | if ((b1 == n1) && (b2 == n1) && (b3 == n2) && (b4 == n2)) |
||
1322 | return; |
||
217 | Franz | 1323 | } |
87 | Franz | 1324 | i->addPoint(FPoint(CurrX, CurrY)); |
1325 | i->addPoint(FPoint(CurrX, CurrY)); |
||
1326 | i->addPoint(FPoint(x1, y1)); |
||
1327 | i->addPoint(FPoint(x1, y1)); |
||
68 | Franz | 1328 | CurrX = x1; |
1329 | CurrY = y1; |
||
1330 | PathLen += 4; |
||
1331 | } |
||
1332 | |||
202 | Franz | 1333 | /*! |
1334 | \fn void SVGPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3) |
||
1335 | \author Franz Schmid |
||
1336 | \date |
||
1337 | \brief |
||
1338 | \param i FPointArray * |
||
1339 | \param x1 double |
||
1340 | \param y1 double |
||
1341 | \param x2 double |
||
1342 | \param y2 double |
||
1343 | \param x3 double |
||
1344 | \param y3 double |
||
1345 | \retval None |
||
1346 | */ |
||
68 | Franz | 1347 | void SVGPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3) |
1348 | { |
||
1349 | if ((!FirstM) && (WasM)) |
||
217 | Franz | 1350 | { |
68 | Franz | 1351 | i->setMarker(); |
1352 | PathLen += 4; |
||
217 | Franz | 1353 | } |
68 | Franz | 1354 | FirstM = false; |
1355 | WasM = false; |
||
87 | Franz | 1356 | if (PathLen > 3) |
217 | Franz | 1357 | { |
87 | Franz | 1358 | FPoint b1 = i->point(i->size()-4); |
1359 | FPoint b2 = i->point(i->size()-3); |
||
1360 | FPoint b3 = i->point(i->size()-2); |
||
1361 | FPoint b4 = i->point(i->size()-1); |
||
1362 | FPoint n1 = FPoint(CurrX, CurrY); |
||
1363 | FPoint n2 = FPoint(x1, y1); |
||
1364 | FPoint n3 = FPoint(x3, y3); |
||
1365 | FPoint n4 = FPoint(x2, y2); |
||
1366 | if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4)) |
||
1367 | return; |
||
217 | Franz | 1368 | } |
87 | Franz | 1369 | i->addPoint(FPoint(CurrX, CurrY)); |
1370 | i->addPoint(FPoint(x1, y1)); |
||
1371 | i->addPoint(FPoint(x3, y3)); |
||
1372 | i->addPoint(FPoint(x2, y2)); |
||
68 | Franz | 1373 | CurrX = x3; |
1374 | CurrY = y3; |
||
1375 | PathLen += 4; |
||
1376 | } |
||
1377 | |||
202 | Franz | 1378 | /*! |
1379 | \fn void SVGPlug::svgClosePath(FPointArray *i) |
||
1380 | \author Franz Schmid |
||
1381 | \date |
||
1382 | \brief |
||
1383 | \param i FPointArray * |
||
1384 | \retval None |
||
1385 | */ |
||
68 | Franz | 1386 | void SVGPlug::svgClosePath(FPointArray *i) |
1387 | { |
||
501 | fschmid | 1388 | if (PathLen > 2) |
217 | Franz | 1389 | { |
501 | fschmid | 1390 | if ((PathLen == 4) || (i->point(i->size()-2).x() != StartX) || (i->point(i->size()-2).y() != StartY)) |
1391 | { |
||
1392 | i->addPoint(i->point(i->size()-2)); |
||
1393 | i->addPoint(i->point(i->size()-3)); |
||
1394 | i->addPoint(FPoint(StartX, StartY)); |
||
1395 | i->addPoint(FPoint(StartX, StartY)); |
||
1396 | } |
||
217 | Franz | 1397 | } |
68 | Franz | 1398 | } |
1399 | |||
202 | Franz | 1400 | /*! |
1401 | \fn QColor SVGPlug::parseColorN( const QString &rgbColor ) |
||
1402 | \author Franz Schmid |
||
1403 | \date |
||
1404 | \brief |
||
1405 | \param rgbColor const QString & |
||
1406 | \retval Qcolor |
||
1407 | */ |
||
68 | Franz | 1408 | QColor SVGPlug::parseColorN( const QString &rgbColor ) |
1409 | { |
||
1410 | int r, g, b; |
||
1411 | keywordToRGB( rgbColor, r, g, b ); |
||
1412 | return QColor( r, g, b ); |
||
1413 | } |
||
1414 | |||
202 | Franz | 1415 | /*! |
1416 | \fn QString SVGPlug::parseColor( const QString &s ) |
||
1417 | \author Franz Schmid |
||
1418 | \date |
||
1419 | \brief |
||
1420 | \param s const QString & |
||
1421 | \retval QString |
||
1422 | */ |
||
68 | Franz | 1423 | QString SVGPlug::parseColor( const QString &s ) |
1424 | { |
||
1425 | QColor c; |
||
1426 | QString ret = "None"; |
||
1427 | if( s.startsWith( "rgb(" ) ) |
||
217 | Franz | 1428 | { |
68 | Franz | 1429 | QString parse = s.stripWhiteSpace(); |
1430 | QStringList colors = QStringList::split( ',', parse ); |
||
1431 | QString r = colors[0].right( ( colors[0].length() - 4 ) ); |
||
1432 | QString g = colors[1]; |
||
1433 | QString b = colors[2].left( ( colors[2].length() - 1 ) ); |
||
1434 | if( r.contains( "%" ) ) |
||
217 | Franz | 1435 | { |
68 | Franz | 1436 | r = r.left( r.length() - 1 ); |
80 | Franz | 1437 | r = QString::number( static_cast<int>( ( static_cast<double>( 255 * r.toDouble() ) / 100.0 ) ) ); |
217 | Franz | 1438 | } |
68 | Franz | 1439 | if( g.contains( "%" ) ) |
217 | Franz | 1440 | { |
68 | Franz | 1441 | g = g.left( g.length() - 1 ); |
80 | Franz | 1442 | g = QString::number( static_cast<int>( ( static_cast<double>( 255 * g.toDouble() ) / 100.0 ) ) ); |
217 | Franz | 1443 | } |
68 | Franz | 1444 | if( b.contains( "%" ) ) |
217 | Franz | 1445 | { |
68 | Franz | 1446 | b = b.left( b.length() - 1 ); |
80 | Franz | 1447 | b = QString::number( static_cast<int>( ( static_cast<double>( 255 * b.toDouble() ) / 100.0 ) ) ); |
217 | Franz | 1448 | } |
68 | Franz | 1449 | c = QColor(r.toInt(), g.toInt(), b.toInt()); |
217 | Franz | 1450 | } |
68 | Franz | 1451 | else |
217 | Franz | 1452 | { |
68 | Franz | 1453 | QString rgbColor = s.stripWhiteSpace(); |
1454 | if( rgbColor.startsWith( "#" ) ) |
||
1455 | c.setNamedColor( rgbColor ); |
||
1456 | else |
||
1457 | c = parseColorN( rgbColor ); |
||
217 | Franz | 1458 | } |
1065 | cbradney | 1459 | ColorList::Iterator it; |
68 | Franz | 1460 | bool found = false; |
1488 | fschmid | 1461 | int r, g, b; |
1462 | QColor tmpR; |
||
3292 | cbradney | 1463 | for (it = currDoc->PageColors.begin(); it != currDoc->PageColors.end(); ++it) |
217 | Franz | 1464 | { |
3292 | cbradney | 1465 | currDoc->PageColors[it.key()].getRGB(&r, &g, &b); |
1488 | fschmid | 1466 | tmpR.setRgb(r, g, b); |
3292 | cbradney | 1467 | if (c == tmpR && currDoc->PageColors[it.key()].getColorModel() == colorModelRGB) |
68 | Franz | 1468 | { |
1469 | ret = it.key(); |
||
1470 | found = true; |
||
1471 | } |
||
217 | Franz | 1472 | } |
68 | Franz | 1473 | if (!found) |
217 | Franz | 1474 | { |
2886 | fschmid | 1475 | ScColor tmp; |
68 | Franz | 1476 | tmp.fromQColor(c); |
3292 | cbradney | 1477 | currDoc->PageColors.insert("FromSVG"+c.name(), tmp); |
3540 | cbradney | 1478 | ScApp->propertiesPalette->updateColorList(); |
68 | Franz | 1479 | ret = "FromSVG"+c.name(); |
217 | Franz | 1480 | } |
68 | Franz | 1481 | return ret; |
1482 | } |
||
1483 | |||
202 | Franz | 1484 | /*! |
1485 | \fn void SVGPlug::parsePA( SvgStyle *obj, const QString &command, const QString ¶ms ) |
||
1486 | \author Franz Schmid |
||
1487 | \date |
||
1488 | \brief |
||
1489 | \param obj SvgStyle * |
||
1490 | \param command const QString & |
||
1491 | \param params const QString & |
||
1492 | \retval None |
||
1493 | */ |
||
68 | Franz | 1494 | void SVGPlug::parsePA( SvgStyle *obj, const QString &command, const QString ¶ms ) |
1495 | { |
||
976 | fschmid | 1496 | if( command == "stroke-opacity" ) |
1394 | cbradney | 1497 | obj->TranspStroke = 1.0 - fromPercentage(params); |
976 | fschmid | 1498 | else if( command == "fill-opacity" ) |
1499 | obj->Transparency = 1.0 - fromPercentage(params); |
||
1500 | else if( command == "opacity" ) |
||
68 | Franz | 1501 | { |
976 | fschmid | 1502 | obj->Transparency = 1.0 - fromPercentage(params); |
1503 | obj->TranspStroke = 1.0 - fromPercentage(params); |
||
1504 | } |
||
1505 | else if( command == "fill" ) |
||
1506 | { |
||
217 | Franz | 1507 | if ((obj->InherCol) && (params == "currentColor")) |
1508 | obj->FillCol = obj->CurCol; |
||
1509 | else if (params == "none") |
||
68 | Franz | 1510 | { |
217 | Franz | 1511 | obj->FillCol = "None"; |
68 | Franz | 1512 | } |
217 | Franz | 1513 | else if( params.startsWith( "url(" ) ) |
68 | Franz | 1514 | { |
217 | Franz | 1515 | unsigned int start = params.find("#") + 1; |
1516 | unsigned int end = params.findRev(")"); |
||
1517 | QString key = params.mid(start, end - start); |
||
2877 | cbradney | 1518 | while (!m_gradients[key].reference.isEmpty()) |
943 | fschmid | 1519 | { |
976 | fschmid | 1520 | QString key2 = m_gradients[key].reference; |
1521 | if (m_gradients[key2].typeValid) |
||
1522 | obj->Gradient = m_gradients[key2].Type; |
||
1523 | if (m_gradients[key2].gradientValid) |
||
1524 | obj->GradCo = m_gradients[key2].gradient; |
||
1525 | if (m_gradients[key2].cspaceValid) |
||
1526 | obj->CSpace = m_gradients[key2].CSpace; |
||
1527 | if (m_gradients[key2].x1Valid) |
||
1528 | obj->GX1 = m_gradients[key2].X1; |
||
1529 | if (m_gradients[key2].y1Valid) |
||
1530 | obj->GY1 = m_gradients[key2].Y1; |
||
1531 | if (m_gradients[key2].x2Valid) |
||
1532 | obj->GX2 = m_gradients[key2].X2; |
||
1533 | if (m_gradients[key2].y2Valid) |
||
1534 | obj->GY2 = m_gradients[key2].Y2; |
||
1535 | if (m_gradients[key2].matrixValid) |
||
1536 | obj->matrixg = m_gradients[key2].matrix; |
||
1537 | key = m_gradients[key].reference; |
||
943 | fschmid | 1538 | } |
976 | fschmid | 1539 | key = params.mid(start, end - start); |
943 | fschmid | 1540 | if (m_gradients[key].typeValid) |
1541 | obj->Gradient = m_gradients[key].Type; |
||
1542 | if (m_gradients[key].gradientValid) |
||
1543 | obj->GradCo = m_gradients[key].gradient; |
||
1544 | if (m_gradients[key].cspaceValid) |
||
1545 | obj->CSpace = m_gradients[key].CSpace; |
||
1546 | if (m_gradients[key].x1Valid) |
||
1547 | obj->GX1 = m_gradients[key].X1; |
||
1548 | if (m_gradients[key].y1Valid) |
||
1549 | obj->GY1 = m_gradients[key].Y1; |
||
1550 | if (m_gradients[key].x2Valid) |
||
1551 | obj->GX2 = m_gradients[key].X2; |
||
1552 | if (m_gradients[key].y2Valid) |
||
1553 | obj->GY2 = m_gradients[key].Y2; |
||
1554 | if (m_gradients[key].matrixValid) |
||
1555 | obj->matrixg = m_gradients[key].matrix; |
||
217 | Franz | 1556 | obj->FillCol = "None"; |
68 | Franz | 1557 | } |
217 | Franz | 1558 | else |
1559 | obj->FillCol = parseColor(params); |
||
68 | Franz | 1560 | } |
1561 | else if( command == "color" ) |
||
1562 | { |
||
1563 | if (params == "none") |
||
1564 | obj->CurCol = "None"; |
||
1565 | else if( params.startsWith( "url(" ) ) |
||
217 | Franz | 1566 | { |
68 | Franz | 1567 | obj->CurCol = "None"; |
217 | Franz | 1568 | } |
68 | Franz | 1569 | else |
217 | Franz | 1570 | { |
68 | Franz | 1571 | obj->CurCol = parseColor(params); |
217 | Franz | 1572 | } |
68 | Franz | 1573 | } |
1574 | else if( command == "stroke" ) |
||
1575 | { |
||
217 | Franz | 1576 | if ((obj->InherCol) && (params == "currentColor")) |
1577 | obj->StrokeCol = obj->CurCol; |
||
1578 | else if (params == "none") |
||
68 | Franz | 1579 | { |
217 | Franz | 1580 | obj->StrokeCol = "None"; |
68 | Franz | 1581 | } |
1582 | else if( params.startsWith( "url(" ) ) |
||
1583 | { |
||
217 | Franz | 1584 | obj->StrokeCol = "None"; |
68 | Franz | 1585 | } |
1586 | else |
||
217 | Franz | 1587 | obj->StrokeCol = parseColor(params); |
1588 | /* if( params == "none" ) |
||
1589 | gc->stroke.setType( VStroke::none ); |
||
1590 | else if( params.startsWith( "url(" ) ) |
||
1591 | { |
||
1592 | unsigned int start = params.find("#") + 1; |
||
1593 | unsigned int end = params.findRev(")"); |
||
1594 | QString key = params.mid( start, end - start ); |
||
1595 | gc->stroke.gradient() = m_gradients[ key ].gradient; |
||
1596 | gc->stroke.gradient().transform( m_gradients[ key ].gradientTransform ); |
||
1597 | gc->stroke.gradient().transform( gc->matrix ); |
||
1598 | gc->stroke.setType( VStroke::grad ); |
||
1599 | } |
||
1600 | else |
||
1601 | { |
||
1602 | parseColor( strokecolor, params ); |
||
1603 | gc->stroke.setType( VStroke::solid ); |
||
1604 | } */ |
||
68 | Franz | 1605 | } |
1606 | else if( command == "stroke-width" ) |
||
1607 | obj->LWidth = parseUnit( params ); |
||
1608 | else if( command == "stroke-linejoin" ) |
||
217 | Franz | 1609 | { |
68 | Franz | 1610 | if( params == "miter" ) |
1611 | obj->PLineJoin = Qt::MiterJoin; |
||
1612 | else if( params == "round" ) |
||
1613 | obj->PLineJoin = Qt::RoundJoin; |
||
1614 | else if( params == "bevel" ) |
||
1615 | obj->PLineJoin = Qt::BevelJoin; |
||
217 | Franz | 1616 | } |
68 | Franz | 1617 | else if( command == "stroke-linecap" ) |
217 | Franz | 1618 | { |
68 | Franz | 1619 | if( params == "butt" ) |
1620 | obj->PLineEnd = Qt::FlatCap; |
||
1621 | else if( params == "round" ) |
||
1622 | obj->PLineEnd = Qt::RoundCap; |
||
1623 | else if( params == "square" ) |
||
1624 | obj->PLineEnd = Qt::SquareCap; |
||
217 | Franz | 1625 | } |
1626 | // else if( command == "stroke-miterlimit" ) |
||
1627 | // gc->stroke.setMiterLimit( params.todouble() ); |
||
68 | Franz | 1628 | else if( command == "stroke-dasharray" ) |
217 | Franz | 1629 | { |
80 | Franz | 1630 | QValueList<double> array; |
68 | Franz | 1631 | if(params != "none") |
217 | Franz | 1632 | { |
68 | Franz | 1633 | QStringList dashes = QStringList::split( ' ', params ); |
217 | Franz | 1634 | for( QStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it ) |
80 | Franz | 1635 | array.append( (*it).toDouble() ); |
217 | Franz | 1636 | } |
68 | Franz | 1637 | obj->dashArray = array; |
217 | Franz | 1638 | } |
68 | Franz | 1639 | else if( command == "stroke-dashoffset" ) |
80 | Franz | 1640 | obj->dashOffset = params.toDouble(); |
68 | Franz | 1641 | else if( command == "font-family" ) |
217 | Franz | 1642 | { |
68 | Franz | 1643 | QString family = params; |
1644 | QString ret = ""; |
||
1645 | family.replace( QRegExp( "'" ) , QChar( ' ' ) ); |
||
3292 | cbradney | 1646 | obj->Family = currDoc->toolSettings.defFont; // family; |
68 | Franz | 1647 | bool found = false; |
2834 | cbradney | 1648 | SCFontsIterator it(PrefsManager::instance()->appPrefs.AvailFonts); |
68 | Franz | 1649 | for ( ; it.current(); ++it) |
217 | Franz | 1650 | { |
68 | Franz | 1651 | QString fam; |
3544 | avox | 1652 | QString fn = it.current()->scName(); |
68 | Franz | 1653 | int pos=fn.find(" "); |
1654 | fam = fn.left(pos); |
||
1655 | if (fam == family) |
||
217 | Franz | 1656 | { |
68 | Franz | 1657 | found = true; |
1658 | ret = fn; |
||
1659 | } |
||
217 | Franz | 1660 | } |
68 | Franz | 1661 | if (found) |
1662 | obj->Family = ret; |
||
1663 | else |
||
3292 | cbradney | 1664 | obj->Family = currDoc->toolSettings.defFont; |
217 | Franz | 1665 | } |
68 | Franz | 1666 | else if( command == "font-size" ) |
111 | Franz | 1667 | obj->FontSize = static_cast<int>(parseUnit(params) * 10.0); |
68 | Franz | 1668 | } |
1669 | |||
202 | Franz | 1670 | /*! |
1671 | \fn void SVGPlug::parseStyle( SvgStyle *obj, const QDomElement &e ) |
||
1672 | \author Franz Schmid |
||
1673 | \date |
||
1674 | \brief |
||
1675 | \param obj SvgStyle * |
||
1676 | \param e const QDomElement & |
||
1677 | \retval None |
||
1678 | */ |
||
68 | Franz | 1679 | void SVGPlug::parseStyle( SvgStyle *obj, const QDomElement &e ) |
1680 | { |
||
1681 | SvgStyle *gc = m_gc.current(); |
||
1682 | if (!gc) |
||
1683 | return; |
||
1684 | if( !e.attribute( "color" ).isEmpty() ) |
||
217 | Franz | 1685 | { |
68 | Franz | 1686 | if (e.attribute( "color" ) == "inherit") |
1687 | gc->InherCol = true; |
||
1688 | else |
||
1689 | parsePA( obj, "color", e.attribute( "color" ) ); |
||
217 | Franz | 1690 | } |
68 | Franz | 1691 | if( !e.attribute( "fill" ).isEmpty() ) |
1692 | parsePA( obj, "fill", e.attribute( "fill" ) ); |
||
1693 | if( !e.attribute( "stroke" ).isEmpty() ) |
||
1694 | parsePA( obj, "stroke", e.attribute( "stroke" ) ); |
||
1695 | if( !e.attribute( "stroke-width" ).isEmpty() ) |
||
1696 | parsePA( obj, "stroke-width", e.attribute( "stroke-width" ) ); |
||
1697 | if( !e.attribute( "stroke-linejoin" ).isEmpty() ) |
||
1698 | parsePA( obj, "stroke-linejoin", e.attribute( "stroke-linejoin" ) ); |
||
1699 | if( !e.attribute( "stroke-linecap" ).isEmpty() ) |
||
1700 | parsePA( obj, "stroke-linecap", e.attribute( "stroke-linecap" ) ); |
||
1701 | if( !e.attribute( "stroke-dasharray" ).isEmpty() ) |
||
1702 | parsePA( obj, "stroke-dasharray", e.attribute( "stroke-dasharray" ) ); |
||
1703 | if( !e.attribute( "stroke-dashoffset" ).isEmpty() ) |
||
1704 | parsePA( obj, "stroke-dashoffset", e.attribute( "stroke-dashoffset" ) ); |
||
1705 | if( !e.attribute( "stroke-opacity" ).isEmpty() ) |
||
1706 | parsePA( obj, "stroke-opacity", e.attribute( "stroke-opacity" ) ); |
||
217 | Franz | 1707 | /* if( !e.attribute( "stroke-miterlimit" ).isEmpty() ) |
1708 | parsePA( obj, "stroke-miterlimit", e.attribute( "stroke-miterlimit" ) ); */ |
||
68 | Franz | 1709 | if( !e.attribute( "fill-opacity" ).isEmpty() ) |
1710 | parsePA( obj, "fill-opacity", e.attribute( "fill-opacity" ) ); |
||
1711 | if( !e.attribute( "opacity" ).isEmpty() ) |
||
1712 | parsePA( obj, "opacity", e.attribute( "opacity" ) ); |
||
1713 | if( !e.attribute( "font-family" ).isEmpty() ) |
||
1714 | parsePA( obj, "font-family", e.attribute( "font-family" ) ); |
||
1715 | if( !e.attribute( "font-size" ).isEmpty() ) |
||
1716 | parsePA( obj, "font-size", e.attribute( "font-size" ) ); |
||
1717 | QString style = e.attribute( "style" ).simplifyWhiteSpace(); |
||
1718 | QStringList substyles = QStringList::split( ';', style ); |
||
217 | Franz | 1719 | for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it ) |
1720 | { |
||
68 | Franz | 1721 | QStringList substyle = QStringList::split( ':', (*it) ); |
1722 | QString command = substyle[0].stripWhiteSpace(); |
||
1723 | QString params = substyle[1].stripWhiteSpace(); |
||
1724 | parsePA( obj, command, params ); |
||
217 | Franz | 1725 | } |
68 | Franz | 1726 | return; |
1727 | } |
||
1728 | |||
202 | Franz | 1729 | /*! |
1730 | \fn void SVGPlug::parseColorStops(GradientHelper *gradient, const QDomElement &e) |
||
1731 | \author Franz Schmid |
||
1732 | \date |
||
1733 | \brief |
||
1734 | \param gradient GradientHelper * |
||
1735 | \param e const QDomElement & |
||
1736 | \retval None |
||
1737 | */ |
||
68 | Franz | 1738 | void SVGPlug::parseColorStops(GradientHelper *gradient, const QDomElement &e) |
1739 | { |
||
1740 | QString Col = "Black"; |
||
705 | fschmid | 1741 | double offset = 0; |
1742 | double opa; |
||
68 | Franz | 1743 | for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) |
217 | Franz | 1744 | { |
296 | Franz | 1745 | opa = 1.0; |
68 | Franz | 1746 | QDomElement stop = n.toElement(); |
1747 | if(stop.tagName() == "stop") |
||
217 | Franz | 1748 | { |
68 | Franz | 1749 | QString temp = stop.attribute( "offset" ); |
1750 | if( temp.contains( '%' ) ) |
||
217 | Franz | 1751 | { |
68 | Franz | 1752 | temp = temp.left( temp.length() - 1 ); |
80 | Franz | 1753 | offset = temp.toDouble() / 100.0; |
217 | Franz | 1754 | } |
68 | Franz | 1755 | else |
80 | Franz | 1756 | offset = temp.toDouble(); |
296 | Franz | 1757 | if( !stop.attribute( "stop-opacity" ).isEmpty() ) |
1758 | opa = fromPercentage(stop.attribute("stop-opacity")); |
||
68 | Franz | 1759 | if( !stop.attribute( "stop-color" ).isEmpty() ) |
1760 | Col = parseColor(stop.attribute("stop-color")); |
||
1761 | else |
||
217 | Franz | 1762 | { |
68 | Franz | 1763 | QString style = stop.attribute( "style" ).simplifyWhiteSpace(); |
1764 | QStringList substyles = QStringList::split( ';', style ); |
||
217 | Franz | 1765 | for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it ) |
1766 | { |
||
68 | Franz | 1767 | QStringList substyle = QStringList::split( ':', (*it) ); |
1768 | QString command = substyle[0].stripWhiteSpace(); |
||
1769 | QString params = substyle[1].stripWhiteSpace(); |
||
1770 | if( command == "stop-color" ) |
||
1771 | Col = parseColor(params); |
||
296 | Franz | 1772 | if( command == "stop-opacity" ) |
1773 | opa = fromPercentage(params); |
||
68 | Franz | 1774 | } |
1775 | } |
||
217 | Franz | 1776 | } |
3292 | cbradney | 1777 | gradient->gradient.addStop( currDoc->PageColors[Col].getRGBColor(), offset, 0.5, opa, Col, 100 ); |
943 | fschmid | 1778 | gradient->gradientValid = true; |
217 | Franz | 1779 | } |
68 | Franz | 1780 | } |
1781 | |||
202 | Franz | 1782 | /*! |
1783 | \fn void SVGPlug::parseGradient( const QDomElement &e ) |
||
1784 | \author Franz Schmid |
||
1785 | \date |
||
1786 | \brief |
||
1787 | \param e const QDomElement & |
||
1788 | \retval None |
||
1789 | */ |
||
68 | Franz | 1790 | void SVGPlug::parseGradient( const QDomElement &e ) |
1791 | { |
||
1792 | GradientHelper gradhelper; |
||
943 | fschmid | 1793 | gradhelper.gradientValid = false; |
68 | Franz | 1794 | gradhelper.gradient.clearStops(); |
1795 | gradhelper.gradient.setRepeatMethod( VGradient::none ); |
||
1796 | |||
1797 | QString href = e.attribute("xlink:href").mid(1); |
||
1798 | double x1, y1, x2, y2; |
||
1799 | if (!href.isEmpty()) |
||
217 | Franz | 1800 | { |
943 | fschmid | 1801 | if (m_gradients.contains(href)) |
1802 | { |
||
1803 | gradhelper.Type = m_gradients[href].Type; |
||
1804 | gradhelper.gradient = m_gradients[href].gradient; |
||
1805 | gradhelper.X1 = m_gradients[href].X1; |
||
1806 | gradhelper.Y1 = m_gradients[href].Y1; |
||
1807 | gradhelper.X2 = m_gradients[href].X2; |
||
1808 | gradhelper.Y2 = m_gradients[href].Y2; |
||
1809 | gradhelper.CSpace = m_gradients[href].CSpace; |
||
1810 | gradhelper.matrix = m_gradients[href].matrix; |
||
1811 | gradhelper.x1Valid = m_gradients[href].x1Valid; |
||
1812 | gradhelper.x2Valid = m_gradients[href].x2Valid; |
||
1813 | gradhelper.y1Valid = m_gradients[href].y1Valid; |
||
1814 | gradhelper.y2Valid = m_gradients[href].y2Valid; |
||
1815 | gradhelper.cspaceValid = m_gradients[href].cspaceValid; |
||
1816 | gradhelper.matrixValid = m_gradients[href].matrixValid; |
||
1817 | gradhelper.gradientValid = m_gradients[href].gradientValid; |
||
1818 | gradhelper.typeValid = m_gradients[href].typeValid; |
||
1819 | } |
||
1820 | gradhelper.reference = href; |
||
217 | Franz | 1821 | } |
296 | Franz | 1822 | if (e.tagName() == "linearGradient") |
1823 | { |
||
943 | fschmid | 1824 | if (e.hasAttribute("x1")) |
1825 | { |
||
1826 | gradhelper.X1 = e.attribute( "x1", "0").toDouble(); |
||
1827 | gradhelper.x1Valid = true; |
||
1828 | } |
||
1829 | if (e.hasAttribute("y1")) |
||
1830 | { |
||
1831 | gradhelper.Y1 = e.attribute( "y1", "0" ).toDouble(); |
||
1832 | gradhelper.y1Valid = true; |
||
1833 | } |
||
1834 | if (e.hasAttribute("x2")) |
||
1835 | { |
||
1836 | gradhelper.X2 = e.attribute( "x2", "1" ).toDouble(); |
||
1837 | gradhelper.x2Valid = true; |
||
1838 | } |
||
1839 | if (e.hasAttribute("y2")) |
||
1840 | { |
||
1841 | gradhelper.Y2 = e.attribute( "y2", "0" ).toDouble(); |
||
1842 | gradhelper.y2Valid = true; |
||
1843 | } |
||
296 | Franz | 1844 | gradhelper.Type = 6; |
943 | fschmid | 1845 | gradhelper.typeValid = true; |
296 | Franz | 1846 | } |
1847 | else |
||
1848 | { |
||
943 | fschmid | 1849 | if (e.hasAttribute("x1")) |
1850 | { |
||
1851 | x1 = e.attribute( "cx", "0.5").toDouble(); |
||
1852 | gradhelper.x1Valid = true; |
||
1853 | } |
||
1854 | if (e.hasAttribute("y1")) |
||
1855 | { |
||
1856 | y1 = e.attribute( "cy", "0.5" ).toDouble(); |
||
1857 | gradhelper.y1Valid = true; |
||
1858 | } |
||
1859 | if (e.hasAttribute("x2")) |
||
1860 | { |
||
1861 | x2 = e.attribute( "r", "0.5" ).toDouble(); |
||
1862 | gradhelper.x2Valid = true; |
||
1863 | } |
||
296 | Franz | 1864 | y2 = y1; |
943 | fschmid | 1865 | gradhelper.y2Valid = true; |
296 | Franz | 1866 | gradhelper.X1 = x1; |
1867 | gradhelper.Y1 = y1; |
||
1868 | gradhelper.X2 = x1 + x2; |
||
1869 | gradhelper.Y2 = y1; |
||
1870 | gradhelper.Type = 7; |
||
943 | fschmid | 1871 | gradhelper.typeValid = true; |
296 | Franz | 1872 | } |
298 | Franz | 1873 | if ( !e.attribute( "gradientUnits" ).isEmpty() ) |
1874 | { |
||
1875 | QString uni = e.attribute( "gradientUnits"); |
||
1876 | if (uni == "userSpaceOnUse") |
||
1877 | gradhelper.CSpace = true; |
||
1878 | else |
||
1879 | gradhelper.CSpace = false; |
||
943 | fschmid | 1880 | gradhelper.cspaceValid = true; |
298 | Franz | 1881 | } |
1882 | else |
||
943 | fschmid | 1883 | { |
298 | Franz | 1884 | gradhelper.CSpace = false; |
943 | fschmid | 1885 | gradhelper.cspaceValid = false; |
1886 | } |
||
296 | Franz | 1887 | QString transf = e.attribute("gradientTransform"); |
1888 | if( !transf.isEmpty() ) |
||
1889 | { |
||
302 | Franz | 1890 | gradhelper.matrix = parseTransform( e.attribute( "gradientTransform" ) ); |
943 | fschmid | 1891 | gradhelper.matrixValid = true; |
296 | Franz | 1892 | } |
943 | fschmid | 1893 | else |
1894 | gradhelper.matrixValid = false; |
||
296 | Franz | 1895 | QString spreadMethod = e.attribute( "spreadMethod" ); |
1896 | if( !spreadMethod.isEmpty() ) |
||
1897 | { |
||
1898 | if( spreadMethod == "reflect" ) |
||
1899 | gradhelper.gradient.setRepeatMethod( VGradient::reflect ); |
||
1900 | else if( spreadMethod == "repeat" ) |
||
1901 | gradhelper.gradient.setRepeatMethod( VGradient::repeat ); |
||
1902 | } |
||
1903 | parseColorStops(&gradhelper, e); |
||
68 | Franz | 1904 | m_gradients.insert(e.attribute("id"), gradhelper); |
1905 | } |
||
1906 | |||
202 | Franz | 1907 | /*! |
1908 | \fn void SVGPlug::parseText(PageItem *ite, const QDomElement &e) |
||
1909 | \author Franz Schmid |
||
1910 | \date |
||
1911 | \brief |
||
1912 | \param ite PageItem * |
||
1913 | \param e const QDomElement & |
||
1914 | \retval None |
||
1915 | */ |
||
215 | Franz | 1916 | QPtrList<PageItem> SVGPlug::parseText(double x, double y, const QDomElement &e) |
68 | Franz | 1917 | { |
1065 | cbradney | 1918 | struct ScText *hg; |
68 | Franz | 1919 | QPainter p; |
215 | Franz | 1920 | QPtrList<PageItem> GElements; |
3207 | craig | 1921 | p.begin(ScApp->view->viewport()); |
3547 | avox | 1922 | // QFont ff(currDoc->UsedFonts[m_gc.current()->Family]); |
1923 | QFont ff(m_gc.current()->Family); |
||
111 | Franz | 1924 | ff.setPointSize(QMAX(qRound(m_gc.current()->FontSize / 10.0), 1)); |
68 | Franz | 1925 | p.setFont(ff); |
215 | Franz | 1926 | setupTransform(e); |
1927 | int desc = p.fontMetrics().descent(); |
||
1928 | int asce = p.fontMetrics().ascent(); |
||
214 | Franz | 1929 | QString Text = QString::fromUtf8(e.text()).stripWhiteSpace(); |
68 | Franz | 1930 | QDomNode c = e.firstChild(); |
1931 | if ((!c.isNull()) && (c.toElement().tagName() == "tspan")) |
||
215 | Franz | 1932 | { |
80 | Franz | 1933 | double tempW = 0; |
68 | Franz | 1934 | for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) |
215 | Franz | 1935 | { |
1936 | tempW = 0; |
||
68 | Franz | 1937 | QDomElement tspan = n.toElement(); |
1938 | addGraphicContext(); |
||
1939 | SvgStyle *gc = m_gc.current(); |
||
1940 | parseStyle(gc, tspan); |
||
3292 | cbradney | 1941 | //int z = ScApp->view->PaintText(x, y, 10, 10, gc->LWidth, gc->FillCol); |
1942 | int z = currDoc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, x, y, 10, 10, gc->LWidth, "None", gc->FillCol, !ScApp->view->Mpressed); |
||
1943 | PageItem* ite = currDoc->Items.at(z); |
||
215 | Franz | 1944 | ite->Extra = 0; |
1945 | ite->TExtra = 0; |
||
1946 | ite->BExtra = 0; |
||
1947 | ite->RExtra = 0; |
||
111 | Franz | 1948 | ite->LineSp = gc->FontSize / 10.0 + 2; |
215 | Franz | 1949 | ite->Height = ite->LineSp+desc+2; |
3207 | craig | 1950 | ScApp->SetNewFont(gc->Family); |
215 | Franz | 1951 | QWMatrix mm = gc->matrix; |
1952 | if( (!tspan.attribute("x").isEmpty()) && (!tspan.attribute("y").isEmpty()) ) |
||
1953 | { |
||
1954 | double x1 = parseUnit( tspan.attribute( "x", "0" ) ); |
||
1955 | double y1 = parseUnit( tspan.attribute( "y", "0" ) ); |
||
1956 | double mx = mm.m11() * x1 + mm.m21() * y1 + mm.dx(); |
||
1957 | double my = mm.m22() * y1 + mm.m12() * x1 + mm.dy(); |
||
1958 | ite->Xpos = mx; |
||
1959 | ite->Ypos = my; |
||
1960 | } |
||
1961 | else |
||
1962 | { |
||
1963 | double mx = mm.m11() * x + mm.m21() * y + mm.dx(); |
||
1964 | double my = mm.m22() * y + mm.m12() * x + mm.dy(); |
||
1965 | ite->Xpos = mx; |
||
1966 | ite->Ypos = my; |
||
1967 | } |
||
68 | Franz | 1968 | if (!tspan.text().isNull()) |
214 | Franz | 1969 | Text = QString::fromUtf8(tspan.text()).stripWhiteSpace(); |
68 | Franz | 1970 | else |
1971 | Text = " "; |
||
217 | Franz | 1972 | ite->IFont = gc->Family; |
1973 | ite->TxtFill = gc->FillCol; |
||
1974 | ite->ShTxtFill = 100; |
||
1975 | ite->TxtStroke = gc->StrokeCol; |
||
1976 | ite->ShTxtStroke = 100; |
||
1977 | ite->ISize = gc->FontSize; |
||
1978 | ite->TxTStyle = 0; |
||
2242 | fschmid | 1979 | ite->TxtScale = 1000; |
1980 | ite->TxtScaleV = 1000; |
||
1981 | ite->TxtBase = 0; |
||
2247 | fschmid | 1982 | ite->TxtShadowX = 50; |
1983 | ite->TxtShadowY = -50; |
||
2257 | fschmid | 1984 | ite->TxtOutline = 10; |
2262 | fschmid | 1985 | ite->TxtUnderPos = -1; |
1986 | ite- |