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