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