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