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