Rev 550 | Rev 592 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
541 | fschmid | 1 | #include "oodrawimp.h" |
2 | #include "oodrawimp.moc" |
||
3 | #if (_MSC_VER >= 1200) |
||
4 | #include "win-config.h" |
||
5 | #else |
||
6 | #include "config.h" |
||
7 | #endif |
||
8 | #include "customfdialog.h" |
||
9 | #include "color.h" |
||
10 | #include "scribusXml.h" |
||
11 | #include "mpalette.h" |
||
12 | #include "prefsfile.h" |
||
13 | #include "prefscontext.h" |
||
14 | #include "prefstable.h" |
||
15 | #include "sxwunzip.h" |
||
544 | fschmid | 16 | #include "serializer.h" |
541 | fschmid | 17 | #include <qfile.h> |
18 | #include <qtextstream.h> |
||
19 | #include <qregexp.h> |
||
20 | #include <qcursor.h> |
||
21 | #include <qdragobject.h> |
||
22 | #include <qdir.h> |
||
23 | #include <qstring.h> |
||
24 | #include <cmath> |
||
25 | |||
26 | using namespace std; |
||
27 | |||
28 | extern QPointArray FlattenPath(FPointArray ina, QValueList<uint> &Segs); |
||
29 | extern bool loadText(QString nam, QString *Buffer); |
||
30 | extern QPixmap loadIcon(QString nam); |
||
31 | extern double RealCWidth(ScribusDoc *doc, QString name, QString ch, int Siz); |
||
32 | extern FPoint GetMaxClipF(FPointArray Clip); |
||
33 | extern PrefsFile* prefsFile; |
||
34 | |||
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 | */ |
||
43 | QString Name() |
||
44 | { |
||
45 | return QObject::tr("Import &Open Office Draw..."); |
||
46 | } |
||
47 | |||
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 | */ |
||
56 | int Type() |
||
57 | { |
||
58 | return 2; |
||
59 | } |
||
60 | |||
61 | int ID() |
||
62 | { |
||
63 | return 12; |
||
64 | } |
||
65 | |||
66 | void Run(QWidget *d, ScribusApp *plug) |
||
67 | { |
||
68 | QString fileName; |
||
69 | if (plug->DLLinput != "") |
||
70 | fileName = plug->DLLinput; |
||
71 | else |
||
72 | { |
||
73 | PrefsContext* prefs = prefsFile->getPluginContext("OODrawImport"); |
||
74 | QString wdir = prefs->get("wdir", "."); |
||
75 | CustomFDialog diaf(d, wdir, QObject::tr("Open"), QObject::tr("Open Office Draw (*.sxd);;All Files (*)")); |
||
76 | if (diaf.exec()) |
||
77 | { |
||
78 | fileName = diaf.selectedFile(); |
||
79 | prefs->set("wdir", fileName.left(fileName.findRev("/"))); |
||
80 | } |
||
81 | else |
||
82 | return; |
||
83 | } |
||
84 | OODPlug *dia = new OODPlug(plug, fileName); |
||
85 | delete dia; |
||
86 | } |
||
87 | |||
88 | OODPlug::OODPlug( ScribusApp *plug, QString fileName ) |
||
89 | { |
||
550 | fschmid | 90 | QString f, f2, f3; |
541 | fschmid | 91 | m_styles.setAutoDelete( true ); |
92 | SxwUnzip* sun = new SxwUnzip(fileName); |
||
93 | stylePath = sun->getFile("styles.xml"); |
||
94 | contentPath = sun->getFile("content.xml"); |
||
550 | fschmid | 95 | metaPath = sun->getFile("meta.xml"); |
541 | fschmid | 96 | delete sun; |
97 | if ((stylePath != NULL) && (contentPath != NULL)) |
||
98 | { |
||
99 | QString docname = fileName.right(fileName.length() - fileName.findRev("/") - 1); |
||
100 | docname = docname.left(docname.findRev(".")); |
||
101 | loadText(stylePath, &f); |
||
102 | if(!inpStyles.setContent(f)) |
||
103 | return; |
||
104 | loadText(contentPath, &f2); |
||
105 | if(!inpContents.setContent(f2)) |
||
106 | return; |
||
107 | QFile f1(stylePath); |
||
108 | f1.remove(); |
||
109 | QFile f2(contentPath); |
||
110 | f2.remove(); |
||
550 | fschmid | 111 | if (metaPath != NULL) |
112 | { |
||
113 | HaveMeta = true; |
||
114 | loadText(metaPath, &f3); |
||
115 | if(!inpMeta.setContent(f3)) |
||
116 | HaveMeta = false; |
||
117 | QFile f3(metaPath); |
||
118 | f3.remove(); |
||
119 | } |
||
120 | else |
||
121 | HaveMeta = false; |
||
541 | fschmid | 122 | } |
123 | else if ((stylePath == NULL) && (contentPath != NULL)) |
||
124 | { |
||
125 | QFile f2(contentPath); |
||
126 | f2.remove(); |
||
127 | } |
||
128 | else if ((stylePath != NULL) && (contentPath == NULL)) |
||
129 | { |
||
130 | QFile f1(stylePath); |
||
131 | f1.remove(); |
||
132 | } |
||
133 | Prog = plug; |
||
134 | QString CurDirP = QDir::currentDirPath(); |
||
135 | QFileInfo efp(fileName); |
||
136 | QDir::setCurrent(efp.dirPath()); |
||
137 | convert(); |
||
138 | QDir::setCurrent(CurDirP); |
||
139 | } |
||
140 | |||
141 | void OODPlug::convert() |
||
142 | { |
||
143 | bool ret = false; |
||
544 | fschmid | 144 | int PageCounter = 0; |
541 | fschmid | 145 | createStyleMap( inpStyles ); |
146 | QDomElement docElem = inpContents.documentElement(); |
||
147 | QDomNode automaticStyles = docElem.namedItem( "office:automatic-styles" ); |
||
148 | if( !automaticStyles.isNull() ) |
||
149 | insertStyles( automaticStyles.toElement() ); |
||
150 | QDomNode body = docElem.namedItem( "office:body" ); |
||
151 | QDomNode drawPage = body.namedItem( "draw:page" ); |
||
152 | QDomElement dp = drawPage.toElement(); |
||
153 | QDomElement *master = m_styles[dp.attribute( "draw:master-page-name" )]; |
||
154 | QDomElement *style = m_styles[master->attribute( "style:page-master-name" )]; |
||
155 | QDomElement properties = style->namedItem( "style:properties" ).toElement(); |
||
156 | double width = !properties.attribute( "fo:page-width" ).isEmpty() ? parseUnit(properties.attribute( "fo:page-width" ) ) : 550.0; |
||
157 | double height = !properties.attribute( "fo:page-height" ).isEmpty() ? parseUnit(properties.attribute( "fo:page-height" ) ) : 841.0; |
||
158 | if (Prog->DLLinput != "") |
||
159 | Prog->doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false); |
||
160 | else |
||
161 | { |
||
162 | if (!Prog->HaveDoc) |
||
163 | { |
||
164 | Prog->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom"); |
||
165 | ret = true; |
||
166 | } |
||
167 | } |
||
550 | fschmid | 168 | if ((ret) || (Prog->DLLinput != "")) |
169 | { |
||
170 | if (width > height) |
||
171 | Prog->doc->PageOri = 1; |
||
172 | else |
||
173 | Prog->doc->PageOri = 0; |
||
174 | Prog->doc->PageSize = "Custom"; |
||
175 | QDomNode mpg; |
||
176 | QDomElement metaElem = inpMeta.documentElement(); |
||
177 | QDomElement mp = metaElem.namedItem( "office:meta" ).toElement(); |
||
178 | mpg = mp.namedItem( "dc:title" ); |
||
179 | if (!mpg.isNull()) |
||
180 | Prog->doc->DocTitel = QString::fromUtf8(mpg.toElement().text()); |
||
181 | mpg = mp.namedItem( "meta:initial-creator" ); |
||
182 | if (!mpg.isNull()) |
||
183 | Prog->doc->DocAutor = QString::fromUtf8(mpg.toElement().text()); |
||
184 | mpg = mp.namedItem( "dc:description" ); |
||
185 | if (!mpg.isNull()) |
||
186 | Prog->doc->DocComments = QString::fromUtf8(mpg.toElement().text()); |
||
187 | mpg = mp.namedItem( "dc:language" ); |
||
188 | if (!mpg.isNull()) |
||
189 | Prog->doc->DocLangInfo = QString::fromUtf8(mpg.toElement().text()); |
||
190 | mpg = mp.namedItem( "meta:creation-date" ); |
||
191 | if (!mpg.isNull()) |
||
192 | Prog->doc->DocDate = QString::fromUtf8(mpg.toElement().text()); |
||
193 | mpg = mp.namedItem( "dc:creator" ); |
||
194 | if (!mpg.isNull()) |
||
195 | Prog->doc->DocContrib = QString::fromUtf8(mpg.toElement().text()); |
||
196 | mpg = mp.namedItem( "meta:keywords" ); |
||
197 | if (!mpg.isNull()) |
||
198 | { |
||
199 | QString Keys = ""; |
||
200 | for( QDomNode n = mpg.firstChild(); !n.isNull(); n = n.nextSibling() ) |
||
201 | { |
||
202 | Keys += QString::fromUtf8(n.toElement().text())+", "; |
||
203 | } |
||
204 | if (Keys.length() > 2) |
||
205 | Prog->doc->DocKeyWords = Keys.left(Keys.length()-2); |
||
206 | } |
||
207 | } |
||
541 | fschmid | 208 | Doku = Prog->doc; |
209 | Prog->view->Deselect(); |
||
210 | Elements.clear(); |
||
211 | Doku->loading = true; |
||
212 | Doku->DoDrawing = false; |
||
213 | Prog->view->setUpdatesEnabled(false); |
||
214 | Prog->ScriptRunning = true; |
||
215 | qApp->setOverrideCursor(QCursor(Qt::waitCursor), true); |
||
216 | if (!Doku->PageColors.contains("Black")) |
||
217 | Doku->PageColors.insert("Black", CMYKColor(0, 0, 0, 255)); |
||
218 | for( QDomNode drawPag = body.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling() ) |
||
219 | { |
||
220 | QDomElement dpg = drawPag.toElement(); |
||
545 | fschmid | 221 | if (Prog->DLLinput != "") |
544 | fschmid | 222 | Prog->view->addPage(PageCounter); |
545 | fschmid | 223 | PageCounter++; |
541 | fschmid | 224 | m_styleStack.clear(); |
225 | fillStyleStack( dpg ); |
||
226 | parseGroup( dpg ); |
||
227 | } |
||
544 | fschmid | 228 | if ((Elements.count() > 1) && (Prog->DLLinput == "")) |
541 | fschmid | 229 | { |
230 | Prog->view->SelItem.clear(); |
||
231 | for (uint a = 0; a < Elements.count(); ++a) |
||
232 | { |
||
233 | Elements.at(a)->Groups.push(Doku->GroupCounter); |
||
234 | if (!ret) |
||
235 | Prog->view->SelItem.append(Elements.at(a)); |
||
236 | } |
||
237 | Doku->GroupCounter++; |
||
238 | } |
||
239 | Doku->DoDrawing = true; |
||
240 | Prog->view->setUpdatesEnabled(true); |
||
241 | Prog->ScriptRunning = false; |
||
242 | if (Prog->DLLinput == "") |
||
243 | Doku->loading = false; |
||
244 | qApp->setOverrideCursor(QCursor(Qt::arrowCursor), true); |
||
245 | if ((Elements.count() > 0) && (!ret) && (Prog->DLLinput == "")) |
||
246 | { |
||
247 | Doku->DragP = true; |
||
248 | Doku->DraggedElem = 0; |
||
249 | Doku->DragElements.clear(); |
||
250 | for (uint dre=0; dre<Elements.count(); ++dre) |
||
251 | { |
||
252 | Doku->DragElements.append(Elements.at(dre)->ItemNr); |
||
253 | } |
||
254 | ScriXmlDoc *ss = new ScriXmlDoc(); |
||
255 | Prog->view->setGroupRect(); |
||
256 | QDragObject *dr = new QTextDrag(ss->WriteElem(&Prog->view->SelItem, Doku, Prog->view), Prog->view->viewport()); |
||
257 | Prog->view->DeleteItem(); |
||
258 | dr->setPixmap(loadIcon("DragPix.xpm")); |
||
259 | dr->drag(); |
||
260 | delete ss; |
||
261 | Doku->DragP = false; |
||
262 | Doku->DraggedElem = 0; |
||
263 | Doku->DragElements.clear(); |
||
264 | } |
||
265 | else |
||
266 | { |
||
267 | Doku->setUnModified(); |
||
268 | Prog->slotDocCh(); |
||
269 | } |
||
545 | fschmid | 270 | Prog->DLLinput = ""; |
541 | fschmid | 271 | } |
272 | |||
273 | void OODPlug::parseGroup(const QDomElement &e) |
||
274 | { |
||
275 | QPtrList<PageItem> GElements; |
||
276 | FPointArray ImgClip; |
||
277 | ImgClip.resize(0); |
||
545 | fschmid | 278 | VGradient gradient; |
279 | double GradientAngle; |
||
280 | bool HaveGradient = false; |
||
281 | int GradientType = 0; |
||
541 | fschmid | 282 | double BaseX = Doku->ActPage->Xoffset; |
283 | double BaseY = Doku->ActPage->Yoffset; |
||
284 | double lwidth = 0; |
||
544 | fschmid | 285 | double x, y, w, h; |
546 | fschmid | 286 | double FillTrans = 0; |
547 | fschmid | 287 | double StrokeTrans = 0; |
548 | fschmid | 288 | QValueList<double> dashes; |
541 | fschmid | 289 | for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) |
290 | { |
||
291 | QString StrokeColor = "None"; |
||
292 | QString FillColor = "None"; |
||
546 | fschmid | 293 | FillTrans = 0; |
547 | fschmid | 294 | StrokeTrans = 0; |
541 | fschmid | 295 | int z = -1; |
548 | fschmid | 296 | dashes.clear(); |
541 | fschmid | 297 | QDomElement b = n.toElement(); |
298 | if( b.isNull() ) |
||
299 | continue; |
||
300 | QString STag = b.tagName(); |
||
547 | fschmid | 301 | QString drawID = b.attribute("draw:name"); |
541 | fschmid | 302 | storeObjectStyles(b); |
303 | if( m_styleStack.hasAttribute("draw:stroke")) |
||
304 | { |
||
544 | fschmid | 305 | if( m_styleStack.attribute( "draw:stroke" ) == "none" ) |
306 | lwidth = 0.0; |
||
307 | else |
||
308 | { |
||
309 | if( m_styleStack.hasAttribute("svg:stroke-width")) |
||
310 | { |
||
311 | lwidth = parseUnit(m_styleStack.attribute("svg:stroke-width")); |
||
312 | if (lwidth == 0) |
||
313 | lwidth = 1; |
||
314 | } |
||
315 | if( m_styleStack.hasAttribute("svg:stroke-color")) |
||
316 | StrokeColor = parseColor(m_styleStack.attribute("svg:stroke-color")); |
||
547 | fschmid | 317 | if( m_styleStack.hasAttribute( "svg:stroke-opacity" ) ) |
318 | StrokeTrans = m_styleStack.attribute( "svg:stroke-opacity" ).remove( '%' ).toDouble() / 100.0; |
||
548 | fschmid | 319 | if( m_styleStack.attribute( "draw:stroke" ) == "dash" ) |
320 | { |
||
321 | QString style = m_styleStack.attribute( "draw:stroke-dash" ); |
||
322 | if( style == "Ultrafine Dashed") |
||
323 | dashes << 1.4 << 1.4; |
||
324 | else if( style == "Fine Dashed" ) |
||
325 | dashes << 14.4 << 14.4; |
||
326 | else if( style == "Fine Dotted") |
||
327 | dashes << 13 << 13; |
||
328 | else if( style == "Ultrafine 2 Dots 3 Dashes") |
||
329 | dashes << 1.45 << 3.6 << 1.45 << 3.6 << 7.2 << 3.6 << 7.2 << 3.6 << 7.2 << 3.6; |
||
330 | else if( style == "Line with Fine Dots") |
||
331 | { |
||
332 | dashes << 56.9 << 4.31; |
||
333 | for (int dd = 0; dd < 10; ++ dd) |
||
334 | { |
||
335 | dashes << 8.6 << 4.31; |
||
336 | } |
||
337 | } |
||
338 | else if( style == "2 Dots 1 Dash" ) |
||
339 | dashes << 2.8 << 5.75 << 2.8 << 5.75 << 5.75 << 5.75; |
||
340 | } |
||
544 | fschmid | 341 | } |
541 | fschmid | 342 | } |
343 | if( m_styleStack.hasAttribute( "draw:fill" ) ) |
||
344 | { |
||
345 | QString fill = m_styleStack.attribute( "draw:fill" ); |
||
346 | if( fill == "solid" ) |
||
347 | { |
||
348 | if( m_styleStack.hasAttribute( "draw:fill-color" ) ) |
||
349 | FillColor = parseColor( m_styleStack.attribute("draw:fill-color")); |
||
546 | fschmid | 350 | if( m_styleStack.hasAttribute( "draw:transparency" ) ) |
351 | FillTrans = m_styleStack.attribute( "draw:transparency" ).remove( '%' ).toDouble() / 100.0; |
||
541 | fschmid | 352 | } |
545 | fschmid | 353 | else if( fill == "gradient" ) |
354 | { |
||
355 | HaveGradient = true; |
||
356 | gradient.clearStops(); |
||
357 | gradient.setRepeatMethod( VGradient::none ); |
||
358 | QString style = m_styleStack.attribute( "draw:fill-gradient-name" ); |
||
359 | QDomElement* draw = m_draws[style]; |
||
360 | if( draw ) |
||
361 | { |
||
362 | double border = 0.0; |
||
546 | fschmid | 363 | int shadeS = 100; |
364 | int shadeE = 100; |
||
545 | fschmid | 365 | if( draw->hasAttribute( "draw:border" ) ) |
366 | border += draw->attribute( "draw:border" ).remove( '%' ).toDouble() / 100.0; |
||
546 | fschmid | 367 | if( draw->hasAttribute( "draw:start-intensity" ) ) |
368 | shadeS = draw->attribute( "draw:start-intensity" ).remove( '%' ).toInt(); |
||
369 | if( draw->hasAttribute( "draw:end-intensity" ) ) |
||
370 | shadeE = draw->attribute( "draw:end-intensity" ).remove( '%' ).toInt(); |
||
545 | fschmid | 371 | QString type = draw->attribute( "draw:style" ); |
372 | if( type == "linear" || type == "axial" ) |
||
373 | { |
||
374 | gradient.setType( VGradient::linear ); |
||
375 | GradientAngle = draw->attribute( "draw:angle" ).toDouble() / 10; |
||
376 | GradientType = 1; |
||
377 | } |
||
546 | fschmid | 378 | QString c, c2; |
379 | c = parseColor( draw->attribute( "draw:start-color" ) ); |
||
380 | c2 = parseColor( draw->attribute( "draw:end-color" ) ); |
||
381 | if ((GradientAngle > 90) && (GradientAngle < 271)) |
||
382 | { |
||
383 | gradient.addStop( Doku->PageColors[c2].getRGBColor(), 0.0, 0.5, 1, c2, shadeE ); |
||
384 | gradient.addStop( Doku->PageColors[c].getRGBColor(), 1.0 - border, 0.5, 1, c, shadeS ); |
||
385 | } |
||
386 | else |
||
387 | { |
||
388 | gradient.addStop( Doku->PageColors[c].getRGBColor(), border, 0.5, 1, c, shadeS ); |
||
389 | gradient.addStop( Doku->PageColors[c2].getRGBColor(), 1.0, 0.5, 1, c2, shadeE ); |
||
390 | } |
||
545 | fschmid | 391 | } |
392 | } |
||
541 | fschmid | 393 | } |
545 | fschmid | 394 | if( STag == "draw:g" ) |
541 | fschmid | 395 | { |
545 | fschmid | 396 | parseGroup( b ); |
548 | fschmid | 397 | for (uint gr = 0; gr < GElements.count(); ++gr) |
398 | { |
||
399 | GElements.at(gr)->Groups.push(Doku->GroupCounter); |
||
400 | } |
||
401 | GElements.clear(); |
||
402 | Doku->GroupCounter++; |
||
545 | fschmid | 403 | } |
404 | else if( STag == "draw:rect" ) |
||
405 | { |
||
544 | fschmid | 406 | x = parseUnit(b.attribute("svg:x")); |
407 | y = parseUnit(b.attribute("svg:y")) ; |
||
408 | w = parseUnit(b.attribute("svg:width")); |
||
409 | h = parseUnit(b.attribute("svg:height")); |
||
541 | fschmid | 410 | double corner = parseUnit(b.attribute("draw:corner-radius")); |
411 | z = Prog->view->PaintRect(BaseX+x, BaseY+y, w, h, lwidth, FillColor, StrokeColor); |
||
412 | PageItem* ite = Doku->Items.at(z); |
||
413 | if (corner != 0) |
||
414 | { |
||
415 | ite->RadRect = corner; |
||
416 | Prog->view->SetFrameRound(ite); |
||
417 | } |
||
418 | } |
||
544 | fschmid | 419 | else if( STag == "draw:circle" || STag == "draw:ellipse" ) |
420 | { |
||
421 | x = parseUnit(b.attribute("svg:x")); |
||
422 | y = parseUnit(b.attribute("svg:y")) ; |
||
423 | w = parseUnit(b.attribute("svg:width")); |
||
424 | h = parseUnit(b.attribute("svg:height")); |
||
425 | z = Prog->view->PaintEllipse(BaseX+x, BaseY+y, w, h, lwidth, FillColor, StrokeColor); |
||
426 | } |
||
427 | else if( STag == "draw:line" ) // line |
||
428 | { |
||
429 | double x1 = b.attribute( "svg:x1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "svg:x1" ) ); |
||
430 | double y1 = b.attribute( "svg:y1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "svg:y1" ) ); |
||
431 | double x2 = b.attribute( "svg:x2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "svg:x2" ) ); |
||
432 | double y2 = b.attribute( "svg:y2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "svg:y2" ) ); |
||
433 | z = Prog->view->PaintPoly(BaseX, BaseY, 10, 10, lwidth, "None", StrokeColor); |
||
434 | PageItem* ite = Doku->Items.at(z); |
||
435 | ite->PoLine.resize(4); |
||
436 | ite->PoLine.setPoint(0, FPoint(x1, y1)); |
||
437 | ite->PoLine.setPoint(1, FPoint(x1, y1)); |
||
438 | ite->PoLine.setPoint(2, FPoint(x2, y2)); |
||
439 | ite->PoLine.setPoint(3, FPoint(x2, y2)); |
||
440 | FPoint wh = GetMaxClipF(ite->PoLine); |
||
441 | ite->Width = wh.x(); |
||
442 | ite->Height = wh.y(); |
||
550 | fschmid | 443 | ite->ClipEdited = true; |
444 | ite->FrameType = 3; |
||
548 | fschmid | 445 | if (!b.hasAttribute("draw:transform")) |
446 | { |
||
447 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
||
448 | Prog->view->AdjustItemSize(ite); |
||
449 | } |
||
544 | fschmid | 450 | } |
451 | else if ( STag == "draw:polygon" ) |
||
452 | { |
||
453 | z = Prog->view->PaintPoly(BaseX, BaseY, 10, 10, lwidth, FillColor, StrokeColor); |
||
454 | PageItem* ite = Doku->Items.at(z); |
||
455 | ite->PoLine.resize(0); |
||
456 | appendPoints(&ite->PoLine, b); |
||
457 | FPoint wh = GetMaxClipF(ite->PoLine); |
||
458 | ite->Width = wh.x(); |
||
459 | ite->Height = wh.y(); |
||
550 | fschmid | 460 | ite->ClipEdited = true; |
461 | ite->FrameType = 3; |
||
548 | fschmid | 462 | if (!b.hasAttribute("draw:transform")) |
463 | { |
||
464 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
||
465 | Prog->view->AdjustItemSize(ite); |
||
466 | } |
||
544 | fschmid | 467 | } |
468 | else if( STag == "draw:polyline" ) |
||
469 | { |
||
470 | z = Prog->view->PaintPolyLine(BaseX, BaseY, 10, 10, lwidth, "None", StrokeColor); |
||
471 | PageItem* ite = Doku->Items.at(z); |
||
472 | ite->PoLine.resize(0); |
||
473 | appendPoints(&ite->PoLine, b); |
||
474 | FPoint wh = GetMaxClipF(ite->PoLine); |
||
475 | ite->Width = wh.x(); |
||
476 | ite->Height = wh.y(); |
||
550 | fschmid | 477 | ite->ClipEdited = true; |
478 | ite->FrameType = 3; |
||
548 | fschmid | 479 | if (!b.hasAttribute("draw:transform")) |
480 | { |
||
481 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
||
482 | Prog->view->AdjustItemSize(ite); |
||
483 | } |
||
544 | fschmid | 484 | } |
485 | else if( STag == "draw:path" ) |
||
486 | { |
||
487 | z = Prog->view->PaintPoly(BaseX, BaseY, 10, 10, lwidth, FillColor, StrokeColor); |
||
488 | PageItem* ite = Doku->Items.at(z); |
||
489 | ite->PoLine.resize(0); |
||
490 | if (parseSVG( b.attribute( "svg:d" ), &ite->PoLine )) |
||
491 | ite->PType = 7; |
||
492 | if (ite->PoLine.size() < 4) |
||
493 | { |
||
494 | Prog->view->SelItem.append(ite); |
||
495 | Prog->view->DeleteItem(); |
||
496 | z = -1; |
||
497 | } |
||
498 | else |
||
499 | { |
||
500 | x = parseUnit(b.attribute("svg:x")); |
||
501 | y = parseUnit(b.attribute("svg:y")) ; |
||
502 | w = parseUnit(b.attribute("svg:width")); |
||
503 | h = parseUnit(b.attribute("svg:height")); |
||
504 | double vx = 0; |
||
505 | double vy = 0; |
||
506 | double vw = 1; |
||
507 | double vh = 1; |
||
508 | parseViewBox(b, &vx, &vy, &vw, &vh); |
||
509 | QWMatrix mat; |
||
510 | mat.translate(x, y); |
||
511 | mat.scale(w / vw, h / vh); |
||
512 | ite->PoLine.map(mat); |
||
513 | FPoint wh = GetMaxClipF(ite->PoLine); |
||
514 | ite->Width = wh.x(); |
||
515 | ite->Height = wh.y(); |
||
550 | fschmid | 516 | ite->ClipEdited = true; |
517 | ite->FrameType = 3; |
||
548 | fschmid | 518 | if (!b.hasAttribute("draw:transform")) |
519 | { |
||
520 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
||
521 | Prog->view->AdjustItemSize(ite); |
||
522 | } |
||
544 | fschmid | 523 | } |
524 | } |
||
525 | else if ( STag == "draw:text-box" ) |
||
526 | { |
||
527 | x = parseUnit(b.attribute("svg:x")); |
||
528 | y = parseUnit(b.attribute("svg:y")) ; |
||
529 | w = parseUnit(b.attribute("svg:width")); |
||
530 | h = parseUnit(b.attribute("svg:height")); |
||
550 | fschmid | 531 | z = Prog->view->PaintText(BaseX+x, BaseY+y, w, h+(h*0.1), lwidth, StrokeColor); |
544 | fschmid | 532 | PageItem* ite = Doku->Items.at(z); |
533 | ite->Extra = 0; |
||
534 | ite->TExtra = 0; |
||
535 | ite->BExtra = 0; |
||
536 | ite->RExtra = 0; |
||
537 | bool firstPa = false; |
||
538 | for ( QDomNode n = b.firstChild(); !n.isNull(); n = n.nextSibling() ) |
||
539 | { |
||
547 | fschmid | 540 | int FontSize = Doku->Dsize; |
544 | fschmid | 541 | QDomElement e = n.toElement(); |
547 | fschmid | 542 | if( m_styleStack.hasAttribute("fo:font-family")) |
543 | { |
||
544 | FontSize = m_styleStack.attribute("fo:font-size").remove( "pt" ).toInt(); |
||
545 | } |
||
544 | fschmid | 546 | /* ToDo: Add reading of Textstyles here */ |
547 | Serializer *ss = new Serializer(""); |
||
547 | fschmid | 548 | ss->Objekt = QString::fromUtf8(e.text()); |
549 | ss->GetText(ite, 0, Doku->Dfont, FontSize, firstPa); |
||
544 | fschmid | 550 | delete ss; |
551 | firstPa = true; |
||
552 | } |
||
553 | } |
||
541 | fschmid | 554 | else |
544 | fschmid | 555 | { |
556 | qDebug("Not supported yet: "+STag); |
||
541 | fschmid | 557 | continue; |
544 | fschmid | 558 | } |
541 | fschmid | 559 | if (z != -1) |
560 | { |
||
561 | PageItem* ite = Doku->Items.at(z); |
||
546 | fschmid | 562 | ite->Transparency = FillTrans; |
547 | fschmid | 563 | ite->TranspStroke = StrokeTrans; |
548 | fschmid | 564 | if (dashes.count() != 0) |
565 | ite->DashValues = dashes; |
||
547 | fschmid | 566 | if (drawID != "") |
567 | ite->AnName = drawID; |
||
541 | fschmid | 568 | if (b.hasAttribute("draw:transform")) |
569 | { |
||
546 | fschmid | 570 | parseTransform(&ite->PoLine, b.attribute("draw:transform")); |
545 | fschmid | 571 | ite->ClipEdited = true; |
572 | ite->FrameType = 3; |
||
573 | FPoint wh = GetMaxClipF(ite->PoLine); |
||
574 | ite->Width = wh.x(); |
||
575 | ite->Height = wh.y(); |
||
576 | ite->Clip = FlattenPath(ite->PoLine, ite->Segments); |
||
577 | Prog->view->AdjustItemSize(ite); |
||
541 | fschmid | 578 | } |
545 | fschmid | 579 | if (HaveGradient) |
580 | { |
||
581 | ite->GrType = 0; |
||
582 | ite->fill_gradient = gradient; |
||
583 | if (GradientType == 1) |
||
584 | { |
||
546 | fschmid | 585 | bool flipped = false; |
586 | if ((GradientAngle == 0) || (GradientAngle == 180) || (GradientAngle == 90) || (GradientAngle == 270)) |
||
587 | { |
||
588 | if ((GradientAngle == 0) || (GradientAngle == 180)) |
||
589 | { |
||
590 | ite->GrType = 2; |
||
591 | Prog->view->updateGradientVectors(ite); |
||
592 | } |
||
593 | else if ((GradientAngle == 90) || (GradientAngle == 270)) |
||
594 | { |
||
595 | ite->GrType = 1; |
||
596 | Prog->view->updateGradientVectors(ite); |
||
597 | } |
||
598 | } |
||
599 | else |
||
600 | { |
||
601 | if ((GradientAngle > 90) && (GradientAngle < 270)) |
||
602 | GradientAngle -= 180; |
||
603 | else if ((GradientAngle > 270) && (GradientAngle < 360)) |
||
604 | { |
||
605 | GradientAngle = 360 - GradientAngle; |
||
606 | flipped = true; |
||
607 | } |
||
608 | double xpos; |
||
609 | xpos = (ite->Width / 2) * tan(GradientAngle* 3.1415927 / 180.0) * (ite->Height / ite->Width) + (ite->Width / 2); |
||
610 | if ((xpos < 0) || (xpos > ite->Width)) |
||
611 | { |
||
612 | xpos = (ite->Height / 2)- (ite->Height / 2) * tan(GradientAngle* 3.1415927 / 180.0) * (ite->Height / ite->Width); |
||
613 | if (flipped) |
||
614 | { |
||
615 | ite->GrEndX = ite->Width; |
||
616 | ite->GrEndY = ite->Height - xpos; |
||
617 | ite->GrStartX = 0; |
||
618 | ite->GrStartY = xpos; |
||
619 | } |
||
620 | else |
||
621 | { |
||
622 | ite->GrEndY = xpos; |
||
623 | ite->GrEndX = ite->Width; |
||
624 | ite->GrStartX = 0; |
||
625 | ite->GrStartY = ite->Height - xpos; |
||
626 | } |
||
627 | } |
||
628 | else |
||
629 | { |
||
630 | ite->GrEndX = xpos; |
||
631 | ite->GrEndY = ite->Height; |
||
632 | ite->GrStartX = ite->Width - xpos; |
||
633 | ite->GrStartY = 0; |
||
634 | } |
||
635 | if (flipped) |
||
636 | { |
||
637 | ite->GrEndX = ite->Width - xpos; |
||
638 | ite->GrEndY = ite->Height; |
||
639 | ite->GrStartX = xpos; |
||
640 | ite->GrStartY = 0; |
||
641 | } |
||
642 | ite->GrType = 6; |
||
643 | } |
||
545 | fschmid | 644 | } |
645 | HaveGradient = false; |
||
646 | } |
||
541 | fschmid | 647 | GElements.append(ite); |
648 | Elements.append(ite); |
||
649 | } |
||
650 | } |
||
651 | } |
||
652 | |||
653 | void OODPlug::createStyleMap( QDomDocument &docstyles ) |
||
654 | { |
||
655 | QDomElement styles = docstyles.documentElement(); |
||
656 | if( styles.isNull() ) |
||
657 | return; |
||
658 | |||
659 | QDomNode fixedStyles = styles.namedItem( "office:styles" ); |
||
660 | if( !fixedStyles.isNull() ) |
||
661 | { |
||
545 | fschmid | 662 | insertDraws( fixedStyles.toElement() ); |
541 | fschmid | 663 | insertStyles( fixedStyles.toElement() ); |
664 | } |
||
665 | QDomNode automaticStyles = styles.namedItem( "office:automatic-styles" ); |
||
666 | if( !automaticStyles.isNull() ) |
||
667 | insertStyles( automaticStyles.toElement() ); |
||
668 | |||
669 | QDomNode masterStyles = styles.namedItem( "office:master-styles" ); |
||
670 | if( !masterStyles.isNull() ) |
||
671 | insertStyles( masterStyles.toElement() ); |
||
672 | } |
||
673 | |||
545 | fschmid | 674 | void OODPlug::insertDraws( const QDomElement& styles ) |
675 | { |
||
676 | for( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() ) |
||
677 | { |
||
678 | QDomElement e = n.toElement(); |
||
679 | if( !e.hasAttribute( "draw:name" ) ) |
||
680 | continue; |
||
681 | QString name = e.attribute( "draw:name" ); |
||
682 | m_draws.insert( name, new QDomElement( e ) ); |
||
683 | } |
||
684 | } |
||
685 | |||
541 | fschmid | 686 | void OODPlug::insertStyles( const QDomElement& styles ) |
687 | { |
||
688 | for ( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() ) |
||
689 | { |
||
690 | QDomElement e = n.toElement(); |
||
691 | if( !e.hasAttribute( "style:name" ) ) |
||
692 | continue; |
||
693 | QString name = e.attribute( "style:name" ); |
||
694 | m_styles.insert( name, new QDomElement( e ) ); |
||
695 | } |
||
696 | } |
||
697 | |||
698 | void OODPlug::fillStyleStack( const QDomElement& object ) |
||
699 | { |
||
700 | if( object.hasAttribute( "presentation:style-name" ) ) |
||
701 | addStyles( m_styles[object.attribute( "presentation:style-name" )] ); |
||
702 | if( object.hasAttribute( "draw:style-name" ) ) |
||
703 | addStyles( m_styles[object.attribute( "draw:style-name" )] ); |
||
704 | if( object.hasAttribute( "draw:text-style-name" ) ) |
||
705 | addStyles( m_styles[object.attribute( "draw:text-style-name" )] ); |
||
706 | if( object.hasAttribute( "text:style-name" ) ) |
||
707 | addStyles( m_styles[object.attribute( "text:style-name" )] ); |
||
708 | } |
||
709 | |||
710 | void OODPlug::addStyles( const QDomElement* style ) |
||
711 | { |
||
712 | if( style->hasAttribute( "style:parent-style-name" ) ) |
||
713 | addStyles( m_styles[style->attribute( "style:parent-style-name" )] ); |
||
714 | m_styleStack.push( *style ); |
||
715 | } |
||
716 | |||
717 | void OODPlug::storeObjectStyles( const QDomElement& object ) |
||
718 | { |
||
719 | fillStyleStack( object ); |
||
720 | } |
||
721 | |||
722 | double OODPlug::parseUnit(const QString &unit) |
||
723 | { |
||
724 | QString unitval=unit; |
||
725 | if (unit == "") |
||
726 | return 0.0; |
||
727 | if( unit.right( 2 ) == "pt" ) |
||
728 | unitval.replace( "pt", "" ); |
||
729 | else if( unit.right( 2 ) == "cm" ) |
||
730 | unitval.replace( "cm", "" ); |
||
731 | else if( unit.right( 2 ) == "mm" ) |
||
732 | unitval.replace( "mm" , "" ); |
||
733 | else if( unit.right( 2 ) == "in" ) |
||
734 | unitval.replace( "in", "" ); |
||
735 | else if( unit.right( 2 ) == "px" ) |
||
736 | unitval.replace( "px", "" ); |
||
737 | double value = unitval.toDouble(); |
||
738 | if( unit.right( 2 ) == "pt" ) |
||
739 | value = value; |
||
740 | else if( unit.right( 2 ) == "cm" ) |
||
741 | value = ( value / 2.54 ) * 72; |
||
742 | else if( unit.right( 2 ) == "mm" ) |
||
743 | value = ( value / 25.4 ) * 72; |
||
744 | else if( unit.right( 2 ) == "in" ) |
||
745 | value = value * 72; |
||
746 | else if( unit.right( 2 ) == "px" ) |
||
747 | value = value; |
||
748 | return value; |
||
749 | } |
||
750 | |||
751 | QColor OODPlug::parseColorN( const QString &rgbColor ) |
||
752 | { |
||
753 | int r, g, b; |
||
754 | keywordToRGB( rgbColor, r, g, b ); |
||
755 | return QColor( r, g, b ); |
||
756 | } |
||
757 | |||
758 | QString OODPlug::parseColor( const QString &s ) |
||
759 | { |
||
760 | QColor c; |
||
761 | QString ret = "None"; |
||
762 | if( s.startsWith( "rgb(" ) ) |
||
763 | { |
||
764 | QString parse = s.stripWhiteSpace(); |
||
765 | QStringList colors = QStringList::split( ',', parse ); |
||
766 | QString r = colors[0].right( ( colors[0].length() - 4 ) ); |
||
767 | QString g = colors[1]; |
||
768 | QString b = colors[2].left( ( colors[2].length() - 1 ) ); |
||
769 | if( r.contains( "%" ) ) |
||
770 | { |
||
771 | r = r.left( r.length() - 1 ); |
||
772 | r = QString::number( static_cast<int>( ( static_cast<double>( 255 * r.toDouble() ) / 100.0 ) ) ); |
||
773 | } |
||
774 | if( g.contains( "%" ) ) |
||
775 | { |
||
776 | g = g.left( g.length() - 1 ); |
||
777 | g = QString::number( static_cast<int>( ( static_cast<double>( 255 * g.toDouble() ) / 100.0 ) ) ); |
||
778 | } |
||
779 | if( b.contains( "%" ) ) |
||
780 | { |
||
781 | b = b.left( b.length() - 1 ); |
||
782 | b = QString::number( static_cast<int>( ( static_cast<double>( 255 * b.toDouble() ) / 100.0 ) ) ); |
||
783 | } |
||
784 | c = QColor(r.toInt(), g.toInt(), b.toInt()); |
||
785 | } |
||
786 | else |
||
787 | { |
||
788 | QString rgbColor = s.stripWhiteSpace(); |
||
789 | if( rgbColor.startsWith( "#" ) ) |
||
790 | c.setNamedColor( rgbColor ); |
||
791 | else |
||
792 | c = parseColorN( rgbColor ); |
||
793 | } |
||
794 | CListe::Iterator it; |
||
795 | bool found = false; |
||
796 | for (it = Doku->PageColors.begin(); it != Doku->PageColors.end(); ++it) |
||
797 | { |
||
798 | if (c == Doku->PageColors[it.key()].getRGBColor()) |
||
799 | { |
||
800 | ret = it.key(); |
||
801 | found = true; |
||
802 | } |
||
803 | } |
||
804 | if (!found) |
||
805 | { |
||
806 | CMYKColor tmp; |
||
807 | tmp.fromQColor(c); |
||
808 | Doku->PageColors.insert("FromOODraw"+c.name(), tmp); |
||
809 | Prog->Mpal->Cpal->SetColors(Doku->PageColors); |
||
810 | ret = "FromOODraw"+c.name(); |
||
811 | } |
||
812 | return ret; |
||
813 | } |
||
814 | |||
546 | fschmid | 815 | void OODPlug::parseTransform(FPointArray *composite, const QString &transform) |
541 | fschmid | 816 | { |
545 | fschmid | 817 | double dx, dy; |
818 | QWMatrix result; |
||
541 | fschmid | 819 | QStringList subtransforms = QStringList::split(')', transform); |
820 | QStringList::ConstIterator it = subtransforms.begin(); |
||
821 | QStringList::ConstIterator end = subtransforms.end(); |
||
546 | fschmid | 822 | for (; it != end; ++it) |
541 | fschmid | 823 | { |
824 | QStringList subtransform = QStringList::split('(', (*it)); |
||
825 | subtransform[0] = subtransform[0].stripWhiteSpace().lower(); |
||
826 | subtransform[1] = subtransform[1].simplifyWhiteSpace(); |
||
827 | QRegExp reg("[,( ]"); |
||
828 | QStringList params = QStringList::split(reg, subtransform[1]); |
||
829 | if(subtransform[0].startsWith(";") || subtransform[0].startsWith(",")) |
||
830 | subtransform[0] = subtransform[0].right(subtransform[0].length() - 1); |
||
831 | if(subtransform[0] == "rotate") |
||
546 | fschmid | 832 | { |
833 | result = QWMatrix(); |
||
545 | fschmid | 834 | result.rotate(-parseUnit(params[0]) * 180 / 3.1415927); |
546 | fschmid | 835 | composite->map(result); |
836 | } |
||
541 | fschmid | 837 | else if(subtransform[0] == "translate") |
838 | { |
||
839 | if(params.count() == 2) |
||
840 | { |
||
545 | fschmid | 841 | dx = parseUnit(params[0]); |
842 | dy = parseUnit(params[1]); |
||
541 | fschmid | 843 | } |
844 | else |
||
845 | { |
||
545 | fschmid | 846 | dx = parseUnit(params[0]); |
847 | dy =0.0; |
||
541 | fschmid | 848 | } |
546 | fschmid | 849 | result = QWMatrix(); |
545 | fschmid | 850 | result.translate(dx, dy); |
546 | fschmid | 851 | composite->map(result); |
541 | fschmid | 852 | } |
545 | fschmid | 853 | else if(subtransform[0] == "skewx") |
546 | fschmid | 854 | { |
855 | result = QWMatrix(); |
||
545 | fschmid | 856 | result.shear(-params[0].toDouble(), 0.0); |
546 | fschmid | 857 | composite->map(result); |
858 | } |
||
545 | fschmid | 859 | else if(subtransform[0] == "skewy") |
546 | fschmid | 860 | { |
861 | result = QWMatrix(); |
||
545 | fschmid | 862 | result.shear(0.0, -params[0].toDouble()); |
546 | fschmid | 863 | composite->map(result); |
864 | } |
||
541 | fschmid | 865 | } |
866 | } |
||
867 | |||
544 | fschmid | 868 | void OODPlug::parseViewBox( const QDomElement& object, double *x, double *y, double *w, double *h ) |
541 | fschmid | 869 | { |
544 | fschmid | 870 | if( !object.attribute( "svg:viewBox" ).isEmpty() ) |
871 | { |
||
872 | QString viewbox( object.attribute( "svg:viewBox" ) ); |
||
873 | QStringList points = QStringList::split( ' ', viewbox.replace( QRegExp(","), " ").simplifyWhiteSpace() ); |
||
874 | *x = points[0].toDouble(); |
||
875 | *y = points[1].toDouble(); |
||
876 | *w = points[2].toDouble(); |
||
877 | *h = points[3].toDouble(); |
||
878 | } |
||
541 | fschmid | 879 | } |
880 | |||
544 | fschmid | 881 | void OODPlug::appendPoints(FPointArray *composite, const QDomElement& object) |
541 | fschmid | 882 | { |
544 | fschmid | 883 | double x = parseUnit(object.attribute("svg:x")); |
884 | double y = parseUnit(object.attribute("svg:y")) ; |
||
885 | double w = parseUnit(object.attribute("svg:width")); |
||
886 | double h = parseUnit(object.attribute("svg:height")); |
||
887 | double vx = 0; |
||
888 | double vy = 0; |
||
889 | double vw = 1; |
||
890 | double vh = 1; |
||
891 | parseViewBox(object, &vx, &vy, &vw, &vh); |
||
892 | QStringList ptList = QStringList::split( ' ', object.attribute( "draw:points" ) ); |
||
893 | FPoint point, firstP; |
||
894 | bool bFirst = true; |
||
895 | for( QStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it ) |
||
896 | { |
||
897 | point = FPoint((*it).section( ',', 0, 0 ).toDouble(), (*it).section( ',', 1, 1 ).toDouble()); |
||
898 | if (bFirst) |
||
899 | { |
||
900 | composite->addPoint(point); |
||
901 | composite->addPoint(point); |
||
902 | firstP = point; |
||
903 | bFirst = false; |
||
904 | } |
||
905 | else |
||
906 | { |
||
907 | composite->addPoint(point); |
||
908 | composite->addPoint(point); |
||
909 | composite->addPoint(point); |
||
910 | composite->addPoint(point); |
||
911 | } |
||
912 | } |
||
913 | composite->addPoint(firstP); |
||
914 | composite->addPoint(firstP); |
||
915 | QWMatrix mat; |
||
916 | mat.translate(x, y); |
||
917 | mat.scale(w / vw, h / vh); |
||
918 | composite->map(mat); |
||
541 | fschmid | 919 | } |
920 | |||
544 | fschmid | 921 | const char * OODPlug::getCoord( const char *ptr, double &number ) |
541 | fschmid | 922 | { |
923 | int integer, exponent; |
||
924 | double decimal, frac; |
||
925 | int sign, expsign; |
||
926 | |||
927 | exponent = 0; |
||
928 | integer = 0; |
||
929 | frac = 1.0; |
||
930 | decimal = 0; |
||
931 | sign = 1; |
||
932 | expsign = 1; |
||
933 | |||
544 | fschmid | 934 | // read the sign |
541 | fschmid | 935 | if(*ptr == '+') |
936 | ptr++; |
||
937 | else if(*ptr == '-') |
||
938 | { |
||
939 | ptr++; |
||
940 | sign = -1; |
||
941 | } |
||
942 | |||
544 | fschmid | 943 | // read the integer part |
541 | fschmid | 944 | while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') |
945 | integer = (integer * 10) + *(ptr++) - '0'; |
||
544 | fschmid | 946 | if(*ptr == '.') // read the decimals |
541 | fschmid | 947 | { |
948 | ptr++; |
||
949 | while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') |
||
950 | decimal += (*(ptr++) - '0') * (frac *= 0.1); |
||
951 | } |
||
952 | |||
544 | fschmid | 953 | if(*ptr == 'e' || *ptr == 'E') // read the exponent part |
541 | fschmid | 954 | { |
955 | ptr++; |
||
956 | |||
544 | fschmid | 957 | // read the sign of the exponent |
541 | fschmid | 958 | if(*ptr == '+') |
959 | ptr++; |
||
960 | else if(*ptr == '-') |
||
961 | { |
||
962 | ptr++; |
||
963 | expsign = -1; |
||
964 | } |
||
965 | |||
966 | exponent = 0; |
||
967 | while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') |
||
968 | { |
||
969 | exponent *= 10; |
||
970 | exponent += *ptr - '0'; |
||
971 | ptr++; |
||
972 | } |
||
973 | } |
||
974 | number = integer + decimal; |
||
975 | number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) ); |
||
976 | |||
544 | fschmid | 977 | // skip the following space |
541 | fschmid | 978 | if(*ptr == ' ') |
979 | ptr++; |
||
980 | |||
981 | return ptr; |
||
982 | } |
||
983 | |||
544 | fschmid | 984 | bool OODPlug::parseSVG( const QString &s, FPointArray *ite ) |
541 | fschmid | 985 | { |
986 | QString d = s; |
||
987 | d = d.replace( QRegExp( "," ), " "); |
||
988 | bool ret = false; |
||
989 | if( !d.isEmpty() ) |
||
990 | { |
||
991 | d = d.simplifyWhiteSpace(); |
||
992 | const char *ptr = d.latin1(); |
||
993 | const char *end = d.latin1() + d.length() + 1; |
||
994 | double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc; |
||
995 | double px1, py1, px2, py2, px3, py3; |
||
996 | bool relative; |
||
997 | FirstM = true; |
||
998 | char command = *(ptr++), lastCommand = ' '; |
||
999 | subpathx = subpathy = curx = cury = contrlx = contrly = 0.0; |
||
1000 | while( ptr < end ) |
||
1001 | { |
||
1002 | if( *ptr == ' ' ) |
||
1003 | ptr++; |
||
1004 | relative = false; |
||
1005 | switch( command ) |
||
1006 | { |
||
1007 | case 'm': |
||
1008 | relative = true; |
||
1009 | case 'M': |
||
1010 | { |
||
1011 | ptr = getCoord( ptr, tox ); |
||
1012 | ptr = getCoord( ptr, toy ); |
||
1013 | WasM = true; |
||
1014 | subpathx = curx = relative ? curx + tox : tox; |
||
1015 | subpathy = cury = relative ? cury + toy : toy; |
||
1016 | svgMoveTo(curx, cury ); |
||
1017 | break; |
||
1018 | } |
||
1019 | case 'l': |
||
1020 | relative = true; |
||
1021 | case 'L': |
||
1022 | { |
||
1023 | ptr = getCoord( ptr, tox ); |
||
1024 | ptr = getCoord( ptr, toy ); |
||
1025 | curx = relative ? curx + tox : tox; |
||
1026 | cury = relative ? cury + toy : toy; |
||
1027 | svgLineTo(ite, curx, cury ); |
||
1028 | break; |
||
1029 | } |
||
1030 | case 'h': |
||
1031 | { |
||
1032 | ptr = getCoord( ptr, tox ); |
||
1033 | curx = curx + tox; |
||
1034 | svgLineTo(ite, curx, cury ); |
||
1035 | break; |
||
1036 | } |
||
1037 | case 'H': |
||
1038 | { |
||
1039 | ptr = getCoord( ptr, tox ); |
||
1040 | curx = tox; |
||
1041 | svgLineTo(ite, curx, cury ); |
||
1042 | break; |
||
1043 | } |
||
1044 | case 'v': |
||
1045 | { |
||
1046 | ptr = getCoord( ptr, toy ); |
||
1047 | cury = cury + toy; |
||
1048 | svgLineTo(ite, curx, cury ); |
||
1049 | break; |
||
1050 | } |
||
1051 | case 'V': |
||
1052 | { |
||
1053 | ptr = getCoord( ptr, toy ); |
||
1054 | cury = toy; |
||
1055 | svgLineTo(ite, curx, cury ); |
||
1056 | break; |
||
1057 | } |
||
1058 | case 'z': |
||
1059 | case 'Z': |
||
1060 | { |
||
587 | fschmid | 1061 | // curx = subpathx; |
1062 | // cury = subpathy; |
||
541 | fschmid | 1063 | svgClosePath(ite); |
1064 | break; |
||
1065 | } |
||
1066 | case 'c': |
||
1067 | relative = true; |
||
1068 | case 'C': |
||
1069 | { |
||
1070 | ptr = getCoord( ptr, x1 ); |
||
1071 | ptr = getCoord( ptr, y1 ); |
||
1072 | ptr = getCoord( ptr, x2 ); |
||
1073 | ptr = getCoord( ptr, y2 ); |
||
1074 | ptr = getCoord( ptr, tox ); |
||
1075 | ptr = getCoord( ptr, toy ); |
||
1076 | px1 = relative ? curx + x1 : x1; |
||
1077 | py1 = relative ? cury + y1 : y1; |
||
1078 | px2 = relative ? curx + x2 : x2; |
||
1079 | py2 = relative ? cury + y2 : y2; |
||
1080 | px3 = relative ? curx + tox : tox; |
||
1081 | py3 = relative ? cury + toy : toy; |
||
1082 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1083 | contrlx = relative ? curx + x2 : x2; |
||
1084 | contrly = relative ? cury + y2 : y2; |
||
1085 | curx = relative ? curx + tox : tox; |
||
1086 | cury = relative ? cury + toy : toy; |
||
1087 | break; |
||
1088 | } |
||
1089 | case 's': |
||
1090 | relative = true; |
||
1091 | case 'S': |
||
1092 | { |
||
1093 | ptr = getCoord( ptr, x2 ); |
||
1094 | ptr = getCoord( ptr, y2 ); |
||
1095 | ptr = getCoord( ptr, tox ); |
||
1096 | ptr = getCoord( ptr, toy ); |
||
1097 | px1 = 2 * curx - contrlx; |
||
1098 | py1 = 2 * cury - contrly; |
||
1099 | px2 = relative ? curx + x2 : x2; |
||
1100 | py2 = relative ? cury + y2 : y2; |
||
1101 | px3 = relative ? curx + tox : tox; |
||
1102 | py3 = relative ? cury + toy : toy; |
||
1103 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1104 | contrlx = relative ? curx + x2 : x2; |
||
1105 | contrly = relative ? cury + y2 : y2; |
||
1106 | curx = relative ? curx + tox : tox; |
||
1107 | cury = relative ? cury + toy : toy; |
||
1108 | break; |
||
1109 | } |
||
1110 | case 'q': |
||
1111 | relative = true; |
||
1112 | case 'Q': |
||
1113 | { |
||
1114 | ptr = getCoord( ptr, x1 ); |
||
1115 | ptr = getCoord( ptr, y1 ); |
||
1116 | ptr = getCoord( ptr, tox ); |
||
1117 | ptr = getCoord( ptr, toy ); |
||
1118 | px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0); |
||
1119 | py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0); |
||
1120 | px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0); |
||
1121 | py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0); |
||
1122 | px3 = relative ? curx + tox : tox; |
||
1123 | py3 = relative ? cury + toy : toy; |
||
1124 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1125 | contrlx = relative ? curx + x1 : (tox + 2 * x1) * (1.0 / 3.0); |
||
1126 | contrly = relative ? cury + y1 : (toy + 2 * y1) * (1.0 / 3.0); |
||
1127 | curx = relative ? curx + tox : tox; |
||
1128 | cury = relative ? cury + toy : toy; |
||
1129 | break; |
||
1130 | } |
||
1131 | case 't': |
||
1132 | relative = true; |
||
1133 | case 'T': |
||
1134 | { |
||
1135 | ptr = getCoord(ptr, tox); |
||
1136 | ptr = getCoord(ptr, toy); |
||
1137 | xc = 2 * curx - contrlx; |
||
1138 | yc = 2 * cury - contrly; |
||
1139 | px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0); |
||
1140 | py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0); |
||
1141 | px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0); |
||
1142 | py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0); |
||
1143 | px3 = relative ? curx + tox : tox; |
||
1144 | py3 = relative ? cury + toy : toy; |
||
1145 | svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 ); |
||
1146 | contrlx = xc; |
||
1147 | contrly = yc; |
||
1148 | curx = relative ? curx + tox : tox; |
||
1149 | cury = relative ? cury + toy : toy; |
||
1150 | break; |
||
1151 | } |
||
1152 | case 'a': |
||
1153 | relative = true; |
||
1154 | case 'A': |
||
1155 | { |
||
1156 | bool largeArc, sweep; |
||
1157 | double angle, rx, ry; |
||
1158 | ptr = getCoord( ptr, rx ); |
||
1159 | ptr = getCoord( ptr, ry ); |
||
1160 | ptr = getCoord( ptr, angle ); |
||
1161 | ptr = getCoord( ptr, tox ); |
||
1162 | largeArc = tox == 1; |
||
1163 | ptr = getCoord( ptr, tox ); |
||
1164 | sweep = tox == 1; |
||
1165 | ptr = getCoord( ptr, tox ); |
||
1166 | ptr = getCoord( ptr, toy ); |
||
1167 | calculateArc(ite, relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep ); |
||
1168 | } |
||
1169 | } |
||
1170 | lastCommand = command; |
||
1171 | if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) |
||
1172 | { |
||
1173 | // there are still coords in this command |
||
1174 | if(command == 'M') |
||
1175 | command = 'L'; |
||
1176 | else if(command == 'm') |
||
1177 | command = 'l'; |
||
1178 | } |
||
1179 | else |
||
1180 | command = *(ptr++); |
||
1181 | |||
1182 | if( lastCommand != 'C' && lastCommand != 'c' && |
||
1183 | lastCommand != 'S' && lastCommand != 's' && |
||
1184 | lastCommand != 'Q' && lastCommand != 'q' && |
||
1185 | lastCommand != 'T' && lastCommand != 't') |
||
1186 | { |
||
1187 | contrlx = curx; |
||
1188 | contrly = cury; |
||
1189 | } |
||
1190 | } |
||
1191 | if ((lastCommand != 'z') && (lastCommand != 'Z')) |
||
1192 | ret = true; |
||
1193 | if (ite->size() > 2) |
||
1194 | { |
||
1195 | if ((ite->point(0).x() == ite->point(ite->size()-2).x()) && (ite->point(0).y() == ite->point(ite->size()-2).y())) |
||
1196 | ret = false; |
||
1197 | } |
||
1198 | } |
||
1199 | return ret; |
||
1200 | } |
||
1201 | |||
544 | fschmid | 1202 | void OODPlug::calculateArc(FPointArray *ite, bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag) |
541 | fschmid | 1203 | { |
1204 | double sin_th, cos_th; |
||
1205 | double a00, a01, a10, a11; |
||
1206 | double x0, y0, x1, y1, xc, yc; |
||
1207 | double d, sfactor, sfactor_sq; |
||
1208 | double th0, th1, th_arc; |
||
1209 | int i, n_segs; |
||
1210 | sin_th = sin(angle * (M_PI / 180.0)); |
||
1211 | cos_th = cos(angle * (M_PI / 180.0)); |
||
1212 | double dx; |
||
1213 | if(!relative) |
||
1214 | dx = (curx - x) / 2.0; |
||
1215 | else |
||
1216 | dx = -x / 2.0; |
||
1217 | double dy; |
||
1218 | if(!relative) |
||
1219 | dy = (cury - y) / 2.0; |
||
1220 | else |
||
1221 | dy = -y / 2.0; |
||
1222 | double _x1 = cos_th * dx + sin_th * dy; |
||
1223 | double _y1 = -sin_th * dx + cos_th * dy; |
||
1224 | double Pr1 = r1 * r1; |
||
1225 | double Pr2 = r2 * r2; |
||
1226 | double Px = _x1 * _x1; |
||
1227 | double Py = _y1 * _y1; |
||
1228 | double check = Px / Pr1 + Py / Pr2; |
||
1229 | if(check > 1) |
||
1230 | { |
||
1231 | r1 = r1 * sqrt(check); |
||
1232 | r2 = r2 * sqrt(check); |
||
1233 | } |
||
1234 | a00 = cos_th / r1; |
||
1235 | a01 = sin_th / r1; |
||
1236 | a10 = -sin_th / r2; |
||
1237 | a11 = cos_th / r2; |
||
1238 | x0 = a00 * curx + a01 * cury; |
||
1239 | y0 = a10 * curx + a11 * cury; |
||
1240 | if(!relative) |
||
1241 | x1 = a00 * x + a01 * y; |
||
1242 | else |
||
1243 | x1 = a00 * (curx + x) + a01 * (cury + y); |
||
1244 | if(!relative) |
||
1245 | y1 = a10 * x + a11 * y; |
||
1246 | else |
||
1247 | y1 = a10 * (curx + x) + a11 * (cury + y); |
||
1248 | d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); |
||
1249 | sfactor_sq = 1.0 / d - 0.25; |
||
1250 | if(sfactor_sq < 0) |
||
1251 | sfactor_sq = 0; |
||
1252 | sfactor = sqrt(sfactor_sq); |
||
1253 | if(sweepFlag == largeArcFlag) |
||
1254 | sfactor = -sfactor; |
||
1255 | xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); |
||
1256 | yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); |
||
1257 | |||
1258 | th0 = atan2(y0 - yc, x0 - xc); |
||
1259 | th1 = atan2(y1 - yc, x1 - xc); |
||
1260 | th_arc = th1 - th0; |
||
1261 | if(th_arc < 0 && sweepFlag) |
||
1262 | th_arc += 2 * M_PI; |
||
1263 | else if(th_arc > 0 && !sweepFlag) |
||
1264 | th_arc -= 2 * M_PI; |
||
1265 | n_segs = static_cast<int>(ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)))); |
||
1266 | for(i = 0; i < n_segs; i++) |
||
1267 | { |
||
1268 | { |
||
1269 | double sin_th, cos_th; |
||
1270 | double a00, a01, a10, a11; |
||
1271 | double x1, y1, x2, y2, x3, y3; |
||
1272 | double t; |
||
1273 | double th_half; |
||
1274 | double _th0 = th0 + i * th_arc / n_segs; |
||
1275 | double _th1 = th0 + (i + 1) * th_arc / n_segs; |
||
1276 | sin_th = sin(angle * (M_PI / 180.0)); |
||
1277 | cos_th = cos(angle * (M_PI / 180.0)); |
||
1278 | a00 = cos_th * r1; |
||
1279 | a01 = -sin_th * r2; |
||
1280 | a10 = sin_th * r1; |
||
1281 | a11 = cos_th * r2; |
||
1282 | th_half = 0.5 * (_th1 - _th0); |
||
1283 | t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half); |
||
1284 | x1 = xc + cos(_th0) - t * sin(_th0); |
||
1285 | y1 = yc + sin(_th0) + t * cos(_th0); |
||
1286 | x3 = xc + cos(_th1); |
||
1287 | y3 = yc + sin(_th1); |
||
1288 | x2 = x3 + t * sin(_th1); |
||
1289 | y2 = y3 - t * cos(_th1); |
||
1290 | 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 ); |
||
1291 | } |
||
1292 | } |
||
1293 | if(!relative) |
||
1294 | curx = x; |
||
1295 | else |
||
1296 | curx += x; |
||
1297 | if(!relative) |
||
1298 | cury = y; |
||
1299 | else |
||
1300 | cury += y; |
||
1301 | } |
||
1302 | |||
544 | fschmid | 1303 | void OODPlug::svgMoveTo(double x1, double y1) |
541 | fschmid | 1304 | { |
1305 | CurrX = x1; |
||
1306 | CurrY = y1; |
||
1307 | StartX = x1; |
||
1308 | StartY = y1; |
||
1309 | PathLen = 0; |
||
1310 | } |
||
1311 | |||
544 | fschmid | 1312 | void OODPlug::svgLineTo(FPointArray *i, double x1, double y1) |
541 | fschmid | 1313 | { |
1314 | if ((!FirstM) && (WasM)) |
||
1315 | { |
||
1316 | i->setMarker(); |
||
1317 | PathLen += 4; |
||
1318 | } |
||
1319 | FirstM = false; |
||
1320 | WasM = false; |
||
1321 | if (i->size() > 3) |
||
1322 | { |
||
1323 | FPoint b1 = i->point(i->size()-4); |
||
1324 | FPoint b2 = i->point(i->size()-3); |
||
1325 | FPoint b3 = i->point(i->size()-2); |
||
1326 | FPoint b4 = i->point(i->size()-1); |
||
1327 | FPoint n1 = FPoint(CurrX, CurrY); |
||
1328 | FPoint n2 = FPoint(x1, y1); |
||
1329 | if ((b1 == n1) && (b2 == n1) && (b3 == n2) && (b4 == n2)) |
||
1330 | return; |
||
1331 | } |
||
1332 | i->addPoint(FPoint(CurrX, CurrY)); |
||
1333 | i->addPoint(FPoint(CurrX, CurrY)); |
||
1334 | i->addPoint(FPoint(x1, y1)); |
||
1335 | i->addPoint(FPoint(x1, y1)); |
||
1336 | CurrX = x1; |
||
1337 | CurrY = y1; |
||
1338 | PathLen += 4; |
||
1339 | } |
||
1340 | |||
544 | fschmid | 1341 | void OODPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3) |
541 | fschmid | 1342 | { |
1343 | if ((!FirstM) && (WasM)) |
||
1344 | { |
||
1345 | i->setMarker(); |
||
1346 | PathLen += 4; |
||
1347 | } |
||
1348 | FirstM = false; |
||
1349 | WasM = false; |
||
1350 | if (PathLen > 3) |
||
1351 | { |
||
1352 | FPoint b1 = i->point(i->size()-4); |
||
1353 | FPoint b2 = i->point(i->size()-3); |
||
1354 | FPoint b3 = i->point(i->size()-2); |
||
1355 | FPoint b4 = i->point(i->size()-1); |
||
1356 | FPoint n1 = FPoint(CurrX, CurrY); |
||
1357 | FPoint n2 = FPoint(x1, y1); |
||
1358 | FPoint n3 = FPoint(x3, y3); |
||
1359 | FPoint n4 = FPoint(x2, y2); |
||
1360 | if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4)) |
||
1361 | return; |
||
1362 | } |
||
1363 | i->addPoint(FPoint(CurrX, CurrY)); |
||
1364 | i->addPoint(FPoint(x1, y1)); |
||
1365 | i->addPoint(FPoint(x3, y3)); |
||
1366 | i->addPoint(FPoint(x2, y2)); |
||
1367 | CurrX = x3; |
||
1368 | CurrY = y3; |
||
1369 | PathLen += 4; |
||
1370 | } |
||
1371 | |||
544 | fschmid | 1372 | void OODPlug::svgClosePath(FPointArray *i) |
541 | fschmid | 1373 | { |
1374 | if (PathLen > 2) |
||
1375 | { |
||
1376 | if ((PathLen == 4) || (i->point(i->size()-2).x() != StartX) || (i->point(i->size()-2).y() != StartY)) |
||
1377 | { |
||
1378 | i->addPoint(i->point(i->size()-2)); |
||
1379 | i->addPoint(i->point(i->size()-3)); |
||
1380 | i->addPoint(FPoint(StartX, StartY)); |
||
1381 | i->addPoint(FPoint(StartX, StartY)); |
||
1382 | } |
||
1383 | } |
||
1384 | } |
||
1385 | |||
544 | fschmid | 1386 | OODPlug::~OODPlug() |
1387 | {} |
||
541 | fschmid | 1388 |