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