summaryrefslogtreecommitdiff
path: root/writerperfect/source/filter/OdgExporter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerperfect/source/filter/OdgExporter.cxx')
-rw-r--r--writerperfect/source/filter/OdgExporter.cxx648
1 files changed, 648 insertions, 0 deletions
diff --git a/writerperfect/source/filter/OdgExporter.cxx b/writerperfect/source/filter/OdgExporter.cxx
new file mode 100644
index 000000000000..429fc8d10dd1
--- /dev/null
+++ b/writerperfect/source/filter/OdgExporter.cxx
@@ -0,0 +1,648 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "OdgExporter.hxx"
+#include "DocumentElement.hxx"
+#include "DocumentHandler.hxx"
+#include <locale.h>
+#include <math.h>
+#include <string>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+OdgExporter::OdgExporter(DocumentHandlerInterface *pHandler):
+ mpHandler(pHandler),
+ miGradientIndex(1),
+ miDashIndex(1),
+ miGraphicsStyleIndex(1),
+ mfWidth(0.0),
+ mfHeight(0.0)
+{
+}
+
+OdgExporter::~OdgExporter()
+{
+
+ for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); iterBody++)
+ {
+ delete (*iterBody);
+ (*iterBody) = NULL;
+ }
+
+ for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mGraphicsAutomaticStyles.begin();
+ iterGraphicsAutomaticStyles != mGraphicsAutomaticStyles.end(); iterGraphicsAutomaticStyles++)
+ {
+ delete((*iterGraphicsAutomaticStyles));
+ }
+
+ for (std::vector<DocumentElement *>::iterator iterGraphicsStrokeDashStyles = mGraphicsStrokeDashStyles.begin();
+ iterGraphicsStrokeDashStyles != mGraphicsStrokeDashStyles.end(); iterGraphicsStrokeDashStyles++)
+ {
+ delete((*iterGraphicsStrokeDashStyles));
+ }
+
+ for (std::vector<DocumentElement *>::iterator iterGraphicsGradientStyles = mGraphicsGradientStyles.begin();
+ iterGraphicsGradientStyles != mGraphicsGradientStyles.end(); iterGraphicsGradientStyles++)
+ {
+ delete((*iterGraphicsGradientStyles));
+ }
+}
+
+void OdgExporter::startGraphics(const ::WPXPropertyList &propList)
+{
+ miGradientIndex = 1;
+ miDashIndex = 1;
+ miGraphicsStyleIndex = 1;
+ mfWidth = 0.0;
+ mfHeight = 0.0;
+
+ if (propList["svg:width"])
+ mfWidth = propList["svg:width"]->getDouble();
+
+ if (propList["svg:height"])
+ mfHeight = propList["svg:height"]->getDouble();
+
+ mpHandler->startDocument();
+ TagOpenElement tmpOfficeDocumentContent("office:document");
+ tmpOfficeDocumentContent.addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/");
+ tmpOfficeDocumentContent.addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0");
+ tmpOfficeDocumentContent.addAttribute("xmlns:ooo", "http://openoffice.org/2004/office");
+ tmpOfficeDocumentContent.addAttribute("office:version", "1.0");
+ tmpOfficeDocumentContent.addAttribute("office:mimetype", "application/vnd.oasis.opendocument.graphics");
+ tmpOfficeDocumentContent.write(mpHandler);
+
+ TagOpenElement("office:settings").write(mpHandler);
+
+ TagOpenElement configItemSetOpenElement("config:config-item-set");
+ configItemSetOpenElement.addAttribute("config:name", "ooo:view-settings");
+ configItemSetOpenElement.write(mpHandler);
+
+ TagOpenElement configItemOpenElement("config:config-item");
+
+ configItemOpenElement.addAttribute("config:name", "VisibleAreaTop");
+ configItemOpenElement.addAttribute("config:type", "int");
+ configItemOpenElement.write(mpHandler);
+ mpHandler->characters("0");
+ mpHandler->endElement("config:config-item");
+
+ configItemOpenElement.addAttribute("config:name", "VisibleAreaLeft");
+ configItemOpenElement.addAttribute("config:type", "int");
+ configItemOpenElement.write(mpHandler);
+ mpHandler->characters("0");
+ mpHandler->endElement("config:config-item");
+
+ configItemOpenElement.addAttribute("config:name", "VisibleAreaWidth");
+ configItemOpenElement.addAttribute("config:type", "int");
+ configItemOpenElement.write(mpHandler);
+ WPXString sWidth; sWidth.sprintf("%li", (unsigned long)(2540 * mfWidth));
+ mpHandler->characters(sWidth);
+ mpHandler->endElement("config:config-item");
+
+ configItemOpenElement.addAttribute("config:name", "VisibleAreaHeight");
+ configItemOpenElement.addAttribute("config:type", "int");
+ configItemOpenElement.write(mpHandler);
+ WPXString sHeight; sHeight.sprintf("%li", (unsigned long)(2540 * mfHeight));
+ mpHandler->characters(sHeight);
+ mpHandler->endElement("config:config-item");
+
+ mpHandler->endElement("config:config-item-set");
+
+ mpHandler->endElement("office:settings");
+}
+
+void OdgExporter::endGraphics()
+{
+ TagOpenElement("office:styles").write(mpHandler);
+
+ for (std::vector<DocumentElement *>::const_iterator iterGraphicsStrokeDashStyles = mGraphicsStrokeDashStyles.begin();
+ iterGraphicsStrokeDashStyles != mGraphicsStrokeDashStyles.end(); iterGraphicsStrokeDashStyles++)
+ {
+ (*iterGraphicsStrokeDashStyles)->write(mpHandler);
+ }
+
+ for (std::vector<DocumentElement *>::const_iterator iterGraphicsGradientStyles = mGraphicsGradientStyles.begin();
+ iterGraphicsGradientStyles != mGraphicsGradientStyles.end(); iterGraphicsGradientStyles++)
+ {
+ (*iterGraphicsGradientStyles)->write(mpHandler);
+ }
+
+ mpHandler->endElement("office:styles");
+
+ TagOpenElement("office:automatic-styles").write(mpHandler);
+
+ // writing out the graphics automatic styles
+ for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mGraphicsAutomaticStyles.begin();
+ iterGraphicsAutomaticStyles != mGraphicsAutomaticStyles.end(); iterGraphicsAutomaticStyles++)
+ {
+ (*iterGraphicsAutomaticStyles)->write(mpHandler);
+ }
+
+ TagOpenElement tmpStylePageLayoutOpenElement("style:page-layout");
+ tmpStylePageLayoutOpenElement.addAttribute("style:name", "PM0");
+ tmpStylePageLayoutOpenElement.write(mpHandler);
+
+ TagOpenElement tmpStylePageLayoutPropertiesOpenElement("style:page-layout-properties");
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-top", "0in");
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-bottom", "0in");
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-left", "0in");
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-right", "0in");
+ WPXString sValue;
+ sValue = doubleToString(mfWidth); sValue.append("in");
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-width", sValue);
+ sValue = doubleToString(mfHeight); sValue.append("in");
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-height", sValue);
+ tmpStylePageLayoutPropertiesOpenElement.addAttribute("style:print-orientation", "portrait");
+ tmpStylePageLayoutPropertiesOpenElement.write(mpHandler);
+
+ mpHandler->endElement("style:page-layout-properties");
+
+ mpHandler->endElement("style:page-layout");
+
+ TagOpenElement tmpStyleStyleOpenElement("style:style");
+ tmpStyleStyleOpenElement.addAttribute("style:name", "dp1");
+ tmpStyleStyleOpenElement.addAttribute("style:family", "drawing-page");
+ tmpStyleStyleOpenElement.write(mpHandler);
+
+ TagOpenElement tmpStyleDrawingPagePropertiesOpenElement("style:drawing-page-properties");
+ // tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:background-size", "border");
+ tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:fill", "none");
+ tmpStyleDrawingPagePropertiesOpenElement.write(mpHandler);
+
+ mpHandler->endElement("style:drawing-page-properties");
+
+ mpHandler->endElement("style:style");
+
+ mpHandler->endElement("office:automatic-styles");
+
+ TagOpenElement("office:master-styles").write(mpHandler);
+
+ TagOpenElement tmpStyleMasterPageOpenElement("style:master-page");
+ tmpStyleMasterPageOpenElement.addAttribute("style:name", "Default");
+ tmpStyleMasterPageOpenElement.addAttribute("style:page-layout-name", "PM0");
+ tmpStyleMasterPageOpenElement.addAttribute("draw:style-name", "dp1");
+ tmpStyleMasterPageOpenElement.write(mpHandler);
+
+ mpHandler->endElement("style:master-page");
+
+ mpHandler->endElement("office:master-styles");
+
+ TagOpenElement("office:body").write(mpHandler);
+
+ TagOpenElement("office:drawing").write(mpHandler);
+
+ TagOpenElement tmpDrawPageOpenElement("draw:page");
+ tmpDrawPageOpenElement.addAttribute("draw:name", "page1");
+ tmpDrawPageOpenElement.addAttribute("draw:style-name", "dp1");
+ tmpDrawPageOpenElement.addAttribute("draw:master-page-name", "Default");
+ tmpDrawPageOpenElement.write(mpHandler);
+
+ for (std::vector<DocumentElement *>::const_iterator bodyIter = mBodyElements.begin();
+ bodyIter != mBodyElements.end(); bodyIter++)
+ {
+ (*bodyIter)->write(mpHandler);
+ }
+
+ mpHandler->endElement("draw:page");
+ mpHandler->endElement("office:drawing");
+ mpHandler->endElement("office:body");
+
+ mpHandler->endElement("office:document");
+
+ mpHandler->endDocument();
+}
+
+void OdgExporter::setStyle(const ::WPXPropertyList & propList, const ::WPXPropertyListVector& gradient)
+{
+ mxStyle = propList;
+ mxGradient = gradient;
+}
+
+void OdgExporter::startLayer(const ::WPXPropertyList & /* propList */)
+{
+}
+
+void OdgExporter::endLayer()
+{
+}
+
+void OdgExporter::drawRectangle(const ::WPXPropertyList &propList)
+{
+ writeGraphicsStyle();
+ TagOpenElement *pDrawRectElement = new TagOpenElement("draw:rect");
+ WPXString sValue;
+ sValue.sprintf("gr%i", miGraphicsStyleIndex-1);
+ pDrawRectElement->addAttribute("draw:style-name", sValue);
+ pDrawRectElement->addAttribute("svg:x", propList["svg:x"]->getStr());
+ pDrawRectElement->addAttribute("svg:y", propList["svg:y"]->getStr());
+ pDrawRectElement->addAttribute("svg:width", propList["svg:width"]->getStr());
+ pDrawRectElement->addAttribute("svg:height", propList["svg:height"]->getStr());
+ // FIXME: what to do when rx != ry ?
+ if (propList["svg:rx"])
+ pDrawRectElement->addAttribute("draw:corner-radius", propList["svg:rx"]->getStr());
+ else
+ pDrawRectElement->addAttribute("draw:corner-radius", "0.0000in");
+ mBodyElements.push_back(pDrawRectElement);
+ mBodyElements.push_back(new TagCloseElement("draw:rect"));
+}
+
+void OdgExporter::drawEllipse(const ::WPXPropertyList &propList)
+{
+ writeGraphicsStyle();
+ TagOpenElement *pDrawEllipseElement = new TagOpenElement("draw:ellipse");
+ WPXString sValue;
+ sValue.sprintf("gr%i", miGraphicsStyleIndex-1);
+ pDrawEllipseElement->addAttribute("draw:style-name", sValue);
+ sValue = doubleToString(2 * propList["svg:rx"]->getDouble()); sValue.append("in");
+ pDrawEllipseElement->addAttribute("svg:width", sValue);
+ sValue = doubleToString(2 * propList["svg:ry"]->getDouble()); sValue.append("in");
+ pDrawEllipseElement->addAttribute("svg:height", sValue);
+ if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
+ {
+ double rotation = propList["libwpg:rotate"]->getDouble();
+ while(rotation < -180)
+ rotation += 360;
+ while(rotation > 180)
+ rotation -= 360;
+ double radrotation = rotation*M_PI/180.0;
+ double deltax = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0)
+ + pow(propList["svg:ry"]->getDouble(), 2.0))*cos(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble())
+ - radrotation ) - propList["svg:rx"]->getDouble();
+ double deltay = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0)
+ + pow(propList["svg:ry"]->getDouble(), 2.0))*sin(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble())
+ - radrotation ) - propList["svg:ry"]->getDouble();
+ sValue = "rotate("; sValue.append(doubleToString(radrotation)); sValue.append(") ");
+ sValue.append("translate("); sValue.append(doubleToString(propList["svg:cx"]->getDouble() - propList["svg:rx"]->getDouble() - deltax));
+ sValue.append("in, ");
+ sValue.append(doubleToString(propList["svg:cy"]->getDouble() - propList["svg:ry"]->getDouble() - deltay)); sValue.append("in)");
+ pDrawEllipseElement->addAttribute("draw:transform", sValue);
+ }
+ else
+ {
+ sValue = doubleToString(propList["svg:cx"]->getDouble()-propList["svg:rx"]->getDouble()); sValue.append("in");
+ pDrawEllipseElement->addAttribute("svg:x", sValue);
+ sValue = doubleToString(propList["svg:cy"]->getDouble()-propList["svg:ry"]->getDouble()); sValue.append("in");
+ pDrawEllipseElement->addAttribute("svg:y", sValue);
+ }
+ mBodyElements.push_back(pDrawEllipseElement);
+ mBodyElements.push_back(new TagCloseElement("draw:ellipse"));
+}
+
+void OdgExporter::drawPolyline(const ::WPXPropertyListVector& vertices)
+{
+ drawPolySomething(vertices, false);
+}
+
+void OdgExporter::drawPolygon(const ::WPXPropertyListVector& vertices)
+{
+ drawPolySomething(vertices, true);
+}
+
+void OdgExporter::drawPolySomething(const ::WPXPropertyListVector& vertices, bool isClosed)
+{
+ if(vertices.count() < 2)
+ return;
+
+ if(vertices.count() == 2)
+ {
+ writeGraphicsStyle();
+ TagOpenElement *pDrawLineElement = new TagOpenElement("draw:line");
+ WPXString sValue;
+ sValue.sprintf("gr%i", miGraphicsStyleIndex-1);
+ pDrawLineElement->addAttribute("draw:style-name", sValue);
+ pDrawLineElement->addAttribute("draw:text-style-name", "P1");
+ pDrawLineElement->addAttribute("draw:layer", "layout");
+ pDrawLineElement->addAttribute("svg:x1", vertices[0]["svg:x"]->getStr());
+ pDrawLineElement->addAttribute("svg:y1", vertices[0]["svg:y"]->getStr());
+ pDrawLineElement->addAttribute("svg:x2", vertices[1]["svg:x"]->getStr());
+ pDrawLineElement->addAttribute("svg:y2", vertices[1]["svg:y"]->getStr());
+ mBodyElements.push_back(pDrawLineElement);
+ mBodyElements.push_back(new TagCloseElement("draw:line"));
+ }
+ else
+ {
+ ::WPXPropertyListVector path;
+ ::WPXPropertyList element;
+
+ for (unsigned long ii = 0; ii < vertices.count(); ii++)
+ {
+ element = vertices[ii];
+ if (ii == 0)
+ element.insert("libwpg:path-action", "M");
+ else
+ element.insert("libwpg:path-action", "L");
+ path.append(element);
+ element.clear();
+ }
+ if (isClosed)
+ {
+ element.insert("libwpg:path-action", "Z");
+ path.append(element);
+ }
+ drawPath(path);
+ }
+}
+
+void OdgExporter::drawPath(const WPXPropertyListVector& path)
+{
+ if(path.count() == 0)
+ return;
+
+ // try to find the bounding box
+ // this is simple convex hull technique, the bounding box might not be
+ // accurate but that should be enough for this purpose
+ double px = path[0]["svg:x"]->getDouble();
+ double py = path[0]["svg:y"]->getDouble();
+ double qx = path[0]["svg:x"]->getDouble();
+ double qy = path[0]["svg:y"]->getDouble();
+ for(unsigned k = 0; k < path.count(); k++)
+ {
+ if (!path[k]["svg:x"] || !path[k]["svg:y"])
+ continue;
+ px = (px > path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : px;
+ py = (py > path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : py;
+ qx = (qx < path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : qx;
+ qy = (qy < path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : qy;
+ if(path[k]["libwpg:path-action"]->getStr() == "C")
+ {
+ px = (px > path[k]["svg:x1"]->getDouble()) ? path[k]["svg:x1"]->getDouble() : px;
+ py = (py > path[k]["svg:y1"]->getDouble()) ? path[k]["svg:y1"]->getDouble() : py;
+ qx = (qx < path[k]["svg:x1"]->getDouble()) ? path[k]["svg:x1"]->getDouble() : qx;
+ qy = (qy < path[k]["svg:y1"]->getDouble()) ? path[k]["svg:y1"]->getDouble() : qy;
+ px = (px > path[k]["svg:x2"]->getDouble()) ? path[k]["svg:x2"]->getDouble() : px;
+ py = (py > path[k]["svg:y2"]->getDouble()) ? path[k]["svg:y2"]->getDouble() : py;
+ qx = (qx < path[k]["svg:x2"]->getDouble()) ? path[k]["svg:x2"]->getDouble() : qx;
+ qy = (qy < path[k]["svg:y2"]->getDouble()) ? path[k]["svg:y2"]->getDouble() : qy;
+ }
+ if(path[k]["libwpg:path-action"]->getStr() == "A")
+ {
+ px = (px > path[k]["svg:x"]->getDouble()-2*path[k]["svg:rx"]->getDouble()) ? path[k]["svg:x"]->getDouble()-2*path[k]["svg:rx"]->getDouble() : px;
+ py = (py > path[k]["svg:y"]->getDouble()-2*path[k]["svg:ry"]->getDouble()) ? path[k]["svg:y"]->getDouble()-2*path[k]["svg:ry"]->getDouble() : py;
+ qx = (qx < path[k]["svg:x"]->getDouble()+2*path[k]["svg:rx"]->getDouble()) ? path[k]["svg:x"]->getDouble()+2*path[k]["svg:rx"]->getDouble() : qx;
+ qy = (qy < path[k]["svg:y"]->getDouble()+2*path[k]["svg:ry"]->getDouble()) ? path[k]["svg:y"]->getDouble()+2*path[k]["svg:ry"]->getDouble() : qy;
+ }
+ }
+ double vw = qx - px;
+ double vh = qy - py;
+
+ writeGraphicsStyle();
+
+ TagOpenElement *pDrawPathElement = new TagOpenElement("draw:path");
+ WPXString sValue;
+ sValue.sprintf("gr%i", miGraphicsStyleIndex-1);
+ pDrawPathElement->addAttribute("draw:style-name", sValue);
+ pDrawPathElement->addAttribute("draw:text-style-name", "P1");
+ pDrawPathElement->addAttribute("draw:layer", "layout");
+ sValue = doubleToString(px); sValue.append("in");
+ pDrawPathElement->addAttribute("svg:x", sValue);
+ sValue = doubleToString(py); sValue.append("in");
+ pDrawPathElement->addAttribute("svg:y", sValue);
+ sValue = doubleToString(vw); sValue.append("in");
+ pDrawPathElement->addAttribute("svg:width", sValue);
+ sValue = doubleToString(vh); sValue.append("in");
+ pDrawPathElement->addAttribute("svg:height", sValue);
+ sValue.sprintf("%i %i %i %i", 0, 0, (unsigned)(vw*2540), (unsigned)(vh*2540));
+ pDrawPathElement->addAttribute("svg:viewBox", sValue);
+
+ sValue.clear();
+ for(unsigned i = 0; i < path.count(); i++)
+ {
+ WPXString sElement;
+ if (path[i]["libwpg:path-action"]->getStr() == "M")
+ {
+ // 2540 is 2.54*1000, 2.54 in = 1 inch
+ sElement.sprintf("M%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
+ (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
+ sValue.append(sElement);
+ }
+ else if (path[i]["libwpg:path-action"]->getStr() == "L")
+ {
+ sElement.sprintf("L%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
+ (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
+ sValue.append(sElement);
+ }
+ else if (path[i]["libwpg:path-action"]->getStr() == "C")
+ {
+ sElement.sprintf("C%i %i %i %i %i %i", (unsigned)((path[i]["svg:x1"]->getDouble()-px)*2540),
+ (int)((path[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x2"]->getDouble()-px)*2540),
+ (int)((path[i]["svg:y2"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
+ (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
+ sValue.append(sElement);
+ }
+ else if (path[i]["libwpg:path-action"]->getStr() == "A")
+ {
+ sElement.sprintf("A%i %i %i %i %i %i %i", (unsigned)((path[i]["svg:rx"]->getDouble())*2540),
+ (int)((path[i]["svg:ry"]->getDouble())*2540), (path[i]["libwpg:rotate"] ? path[i]["libwpg:rotate"]->getInt() : 0),
+ 0, 0, (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
+ sValue.append(sElement);
+ }
+ else if (path[i]["libwpg:path-action"]->getStr() == "Z" && i >= (path.count() - 1))
+ sValue.append(" Z");
+ }
+ pDrawPathElement->addAttribute("svg:d", sValue);
+ mBodyElements.push_back(pDrawPathElement);
+ mBodyElements.push_back(new TagCloseElement("draw:path"));
+}
+
+void OdgExporter::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData& binaryData)
+{
+ if (!propList["libwpg:mime-type"] && propList["libwpg:mime-type"]->getStr().len() <= 0)
+ return;
+ TagOpenElement *pDrawFrameElement = new TagOpenElement("draw:frame");
+
+
+ WPXString sValue;
+ if (propList["svg:x"])
+ pDrawFrameElement->addAttribute("svg:x", propList["svg:x"]->getStr());
+ if (propList["svg:y"])
+ pDrawFrameElement->addAttribute("svg:y", propList["svg:y"]->getStr());
+ if (propList["svg:height"])
+ pDrawFrameElement->addAttribute("svg:height", propList["svg:height"]->getStr());
+ if (propList["svg:width"])
+ pDrawFrameElement->addAttribute("svg:width", propList["svg:width"]->getStr());
+ mBodyElements.push_back(pDrawFrameElement);
+
+ mBodyElements.push_back(new TagOpenElement("draw:image"));
+
+ mBodyElements.push_back(new TagOpenElement("office:binary-data"));
+
+ ::WPXString base64Binary = binaryData.getBase64Data();
+ mBodyElements.push_back(new CharDataElement(base64Binary.cstr()));
+
+ mBodyElements.push_back(new TagCloseElement("office:binary-data"));
+
+ mBodyElements.push_back(new TagCloseElement("draw:image"));
+
+ mBodyElements.push_back(new TagCloseElement("draw:frame"));
+}
+
+void OdgExporter::writeGraphicsStyle()
+{
+#if 0
+ if(mxStyle["libwpg:stroke-solid"] && !mxStyle["libwpg:stroke-solid"]->getInt() && (mxDashArray.count() >=2 ) )
+ {
+ // ODG only supports dashes with the same length of spaces inbetween
+ // here we take the first space and assume everything else the same
+ // note that dash length is written in percentage ?????????????????
+ double distance = mxDashArray.at(1);
+ TagOpenElement *pDrawStrokeDashElement = new TagOpenElement("draw:stroke-dash");
+ pDrawStrokeDashElement->addAttribute("draw:style", "rect");
+ WPXString sValue;
+ sValue.sprintf("Dash_%i", miDashIndex++);
+ pDrawStrokeDashElement->addAttribute("draw:name", sValue);
+ sValue = doubleToString(distance); sValue.append("in");
+ pDrawStrokeDashElement->addAttribute("draw:distance", sValue);
+ WPXString sName;
+ // We have to find out how to do this intelligently, since the ODF is allowing only
+ // two pairs draw:dots1 draw:dots1-length and draw:dots2 draw:dots2-length
+ for(unsigned i = 0; i < mxDashArray.count()/2 && i < 2; i++)
+ {
+ sName.sprintf("draw:dots%i", i+1);
+ pDrawStrokeDashElement->addAttribute(sName.cstr(), "1");
+ sName.sprintf("draw:dots%i-length", i+1);
+ sValue = doubleToString(mxDashArray.at(i*2)); sValue.append("in");
+ pDrawStrokeDashElement->addAttribute(sName.cstr(), sValue);
+ }
+ mGraphicsStrokeDashStyles.push_back(pDrawStrokeDashElement);
+ mGraphicsStrokeDashStyles.push_back(new TagCloseElement("draw:stroke-dash"));
+ }
+#endif
+ if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient" && mxGradient.count() >= 2)
+ {
+ TagOpenElement *pDrawGradientElement = new TagOpenElement("draw:gradient");
+ pDrawGradientElement->addAttribute("draw:style", "linear");
+ WPXString sValue;
+ sValue.sprintf("Gradient_%i", miGradientIndex++);
+ pDrawGradientElement->addAttribute("draw:name", sValue);
+
+ // ODG angle unit is 0.1 degree
+ double angle = mxStyle["draw:angle"] ? -mxStyle["draw:angle"]->getDouble() : 0.0;
+ while(angle < 0)
+ angle += 360;
+ while(angle > 360)
+ angle -= 360;
+
+ sValue.sprintf("%i", (unsigned)(angle*10));
+ pDrawGradientElement->addAttribute("draw:angle", sValue);
+
+ pDrawGradientElement->addAttribute("draw:start-color", mxGradient[0]["svg:stop-color"]->getStr().cstr());
+ pDrawGradientElement->addAttribute("draw:end-color", mxGradient[1]["svg:stop-color"]->getStr().cstr());
+ pDrawGradientElement->addAttribute("draw:start-intensity", "100%");
+ pDrawGradientElement->addAttribute("draw:end-intensity", "100%");
+ pDrawGradientElement->addAttribute("draw:border", "0%");
+ mGraphicsGradientStyles.push_back(pDrawGradientElement);
+ mGraphicsGradientStyles.push_back(new TagCloseElement("draw:gradient"));
+ }
+
+ TagOpenElement *pStyleStyleElement = new TagOpenElement("style:style");
+ WPXString sValue;
+ sValue.sprintf("gr%i", miGraphicsStyleIndex);
+ pStyleStyleElement->addAttribute("style:name", sValue);
+ pStyleStyleElement->addAttribute("style:family", "graphic");
+ pStyleStyleElement->addAttribute("style:parent-style-name", "standard");
+ mGraphicsAutomaticStyles.push_back(pStyleStyleElement);
+
+ TagOpenElement *pStyleGraphicsPropertiesElement = new TagOpenElement("style:graphic-properties");
+
+ if(!(mxStyle["draw:stroke"] && mxStyle["draw:stroke"]->getStr() == "none") && mxStyle["svg:stroke-width"] && mxStyle["svg:stroke-width"]->getDouble() > 0.0)
+ {
+ if (mxStyle["svg:stroke-width"])
+ pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-width", mxStyle["svg:stroke-width"]->getStr());
+
+ if (mxStyle["svg:stroke-color"])
+ pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-color", mxStyle["svg:stroke-color"]->getStr());
+ if (mxStyle["svg:stroke-opacity"] && mxStyle["svg:stroke-opacity"]->getDouble() != 1.0)
+ pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-opacity", mxStyle["svg:stroke-opacity"]->getStr());
+
+
+ if(mxStyle["libwpg:stroke-solid"] && mxStyle["libwpg:stroke-solid"]->getInt())
+ pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "solid");
+#if 0
+ else
+ {
+ pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "dash");
+ sValue.sprintf("Dash_%i", miDashIndex-1);
+ pStyleGraphicsPropertiesElement->addAttribute("draw:stroke-dash", sValue);
+ }
+#endif
+ }
+ else
+ pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "none");
+
+ if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "none")
+ pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none");
+
+ if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "solid")
+ {
+ pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid");
+ if (mxStyle["draw:fill-color"])
+ pStyleGraphicsPropertiesElement->addAttribute("draw:fill-color", mxStyle["draw:fill-color"]->getStr());
+ if (mxStyle["draw:opacity"] && mxStyle["draw:opacity"]->getDouble() != 1.0)
+ pStyleGraphicsPropertiesElement->addAttribute("draw:opacity", mxStyle["draw:opacity"]->getStr());
+ }
+
+ if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient")
+ {
+ if (mxGradient.count() >= 2)
+ {
+ pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "gradient");
+ sValue.sprintf("Gradient_%i", miGradientIndex-1);
+ pStyleGraphicsPropertiesElement->addAttribute("draw:fill-gradient-name", sValue);
+ }
+ else
+ pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none");
+ }
+
+ mGraphicsAutomaticStyles.push_back(pStyleGraphicsPropertiesElement);
+ mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties"));
+
+ mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:style"));
+ miGraphicsStyleIndex++;
+}
+
+WPXString OdgExporter::doubleToString(const double value)
+{
+ WPXString tempString;
+ tempString.sprintf("%.4f", value);
+ std::string decimalPoint(localeconv()->decimal_point);
+ if ((decimalPoint.size() == 0) || (decimalPoint == "."))
+ return tempString;
+ std::string stringValue(tempString.cstr());
+ if (!stringValue.empty())
+ {
+ std::string::size_type pos;
+ while ((pos = stringValue.find(decimalPoint)) != std::string::npos)
+ stringValue.replace(pos,decimalPoint.size(),".");
+ }
+ return WPXString(stringValue.c_str());
+}