summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Alonso <laurent.alonso@inria.fr>2013-08-25 16:03:46 +0200
committerFridrich Štrba <fridrich.strba@bluewin.ch>2013-08-25 16:03:46 +0200
commitc8c89a292846c435c0ba02d6ef768f9ffa99dd5d (patch)
treea5cb0607ad20373a2a9baec04af097f80e298440
parent6fdf57fb028536659727b681a335823189576c14 (diff)
Sync with libwpg
-rw-r--r--src/lib/VSDSVGGenerator.cpp945
-rw-r--r--src/lib/VSDSVGGenerator.h16
2 files changed, 575 insertions, 386 deletions
diff --git a/src/lib/VSDSVGGenerator.cpp b/src/lib/VSDSVGGenerator.cpp
index eb278bc..1dda1ed 100644
--- a/src/lib/VSDSVGGenerator.cpp
+++ b/src/lib/VSDSVGGenerator.cpp
@@ -29,10 +29,12 @@
*/
#include "VSDSVGGenerator.h"
-#include <locale.h>
#include <sstream>
#include <string>
+namespace
+{
+
static std::string doubleToString(const double value)
{
WPXProperty *prop = WPXPropertyFactory::newDoubleProp(value);
@@ -60,38 +62,102 @@ static unsigned stringToColour(const ::WPXString &s)
return val;
}
-libvisio::VSDSVGGenerator::VSDSVGGenerator(libvisio::VSDStringVector &vec): m_gradient(), m_style(), m_gradientIndex(1), m_patternIndex(1), m_shadowIndex(1), m_outputSink(), m_vec(vec)
+} // anomymous namespace
+
+namespace libvisio
{
-}
-libvisio::VSDSVGGenerator::~VSDSVGGenerator()
+struct VSDSVGGeneratorPrivate
{
-}
+ VSDSVGGeneratorPrivate(VSDStringVector &vec, const WPXString &nmSpace);
-void libvisio::VSDSVGGenerator::startGraphics(const WPXPropertyList &propList)
+ void setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &gradient);
+ void writeStyle(bool isClosed=true);
+ void drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed);
+
+ //! return the namespace and the delimiter
+ std::string const &getNamespaceAndDelim() const
+ {
+ return m_nmSpaceAndDelim;
+ }
+ ::WPXPropertyListVector m_gradient;
+ ::WPXPropertyList m_style;
+ int m_gradientIndex, m_shadowIndex;
+ //! index uses when fill=bitmap
+ int m_patternIndex;
+ int m_arrowStartIndex /** start arrow index*/, m_arrowEndIndex /** end arrow index */;
+ //! layerId used if svg:id is not defined when calling startLayer
+ int m_layerId;
+ //! a prefix used to define the svg namespace
+ std::string m_nmSpace;
+ //! a prefix used to define the svg namespace with delimiter
+ std::string m_nmSpaceAndDelim;
+ std::ostringstream m_outputSink;
+ VSDStringVector &m_vec;
+};
+
+VSDSVGGeneratorPrivate::VSDSVGGeneratorPrivate(VSDStringVector &vec, const WPXString &nmSpace) :
+ m_gradient(),
+ m_style(),
+ m_gradientIndex(1),
+ m_shadowIndex(1),
+ m_patternIndex(1),
+ m_arrowStartIndex(1),
+ m_arrowEndIndex(1),
+ m_layerId(1000),
+ m_nmSpace(nmSpace.cstr()),
+ m_nmSpaceAndDelim(""),
+ m_outputSink(),
+ m_vec(vec)
{
- m_outputSink << "<svg:svg version=\"1.1\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ";
- if (propList["svg:width"])
- m_outputSink << "width=\"" << doubleToString(72*(propList["svg:width"]->getDouble())) << "\" ";
- if (propList["svg:height"])
- m_outputSink << "height=\"" << doubleToString(72*(propList["svg:height"]->getDouble())) << "\"";
- m_outputSink << " >\n";
+ if (!m_nmSpace.empty())
+ m_nmSpaceAndDelim = m_nmSpace+":";
}
-void libvisio::VSDSVGGenerator::endGraphics()
+void VSDSVGGeneratorPrivate::drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed)
{
- m_outputSink << "</svg:svg>\n";
- m_vec.append(m_outputSink.str().c_str());
- m_outputSink.str("");
+ if(vertices.count() < 2)
+ return;
+
+ if(vertices.count() == 2)
+ {
+ if (!vertices[0]["svg:x"]||!vertices[0]["svg:y"]||!vertices[1]["svg:x"]||!vertices[1]["svg:y"])
+ return;
+ m_outputSink << "<" << getNamespaceAndDelim() << "line ";
+ m_outputSink << "x1=\"" << doubleToString(72*(vertices[0]["svg:x"]->getDouble())) << "\" y1=\"" << doubleToString(72*(vertices[0]["svg:y"]->getDouble())) << "\" ";
+ m_outputSink << "x2=\"" << doubleToString(72*(vertices[1]["svg:x"]->getDouble())) << "\" y2=\"" << doubleToString(72*(vertices[1]["svg:y"]->getDouble())) << "\"\n";
+ writeStyle();
+ m_outputSink << "/>\n";
+ }
+ else
+ {
+ if (isClosed)
+ m_outputSink << "<" << getNamespaceAndDelim() << "polygon ";
+ else
+ m_outputSink << "<" << getNamespaceAndDelim() << "polyline ";
+
+ m_outputSink << "points=\"";
+ for(unsigned i = 0; i < vertices.count(); i++)
+ {
+ if (!vertices[i]["svg:x"]||!vertices[i]["svg:y"])
+ continue;
+ m_outputSink << doubleToString(72*(vertices[i]["svg:x"]->getDouble())) << " " << doubleToString(72*(vertices[i]["svg:y"]->getDouble()));
+ if (i < vertices.count()-1)
+ m_outputSink << ", ";
+ }
+ m_outputSink << "\"\n";
+ writeStyle(isClosed);
+ m_outputSink << "/>\n";
+ }
}
-void libvisio::VSDSVGGenerator::setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &gradient)
+void VSDSVGGeneratorPrivate::setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &gradient)
{
m_style.clear();
m_style = propList;
m_gradient = gradient;
- if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible")
+ if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible" && m_style["draw:shadow-opacity"])
{
double shadowRed = 0.0;
double shadowGreen = 0.0;
@@ -103,12 +169,15 @@ void libvisio::VSDSVGGenerator::setStyle(const ::WPXPropertyList &propList, cons
shadowGreen = (double)((shadowColour & 0x0000ff00) >> 8)/255.0;
shadowBlue = (double)(shadowColour & 0x000000ff)/255.0;
}
- m_outputSink << "<svg:defs>\n";
- m_outputSink << "<svg:filter filterUnits=\"userSpaceOnUse\" id=\"shadow" << m_shadowIndex++ << "\">";
- m_outputSink << "<svg:feOffset in=\"SourceGraphic\" result=\"offset\" ";
- m_outputSink << "dx=\"" << doubleToString(72*m_style["draw:shadow-offset-x"]->getDouble()) << "\" ";
- m_outputSink << "dy=\"" << doubleToString(72*m_style["draw:shadow-offset-y"]->getDouble()) << "\"/>";
- m_outputSink << "<svg:feColorMatrix in=\"offset\" result=\"offset-color\" type=\"matrix\" values=\"";
+ m_outputSink << "<" << getNamespaceAndDelim() << "defs>\n";
+ m_outputSink << "<" << getNamespaceAndDelim() << "filter filterUnits=\"userSpaceOnUse\" id=\"shadow" << m_shadowIndex++ << "\">";
+ m_outputSink << "<" << getNamespaceAndDelim() << "feOffset in=\"SourceGraphic\" result=\"offset\" ";
+ if (m_style["draw:shadow-offset-x"])
+ m_outputSink << "dx=\"" << doubleToString(72*m_style["draw:shadow-offset-x"]->getDouble()) << "\" ";
+ if (m_style["draw:shadow-offset-y"])
+ m_outputSink << "dy=\"" << doubleToString(72*m_style["draw:shadow-offset-y"]->getDouble()) << "\" ";
+ m_outputSink << "/>";
+ m_outputSink << "<" << getNamespaceAndDelim() << "feColorMatrix in=\"offset\" result=\"offset-color\" type=\"matrix\" values=\"";
m_outputSink << "0 0 0 0 " << doubleToString(shadowRed) ;
m_outputSink << " 0 0 0 0 " << doubleToString(shadowGreen);
m_outputSink << " 0 0 0 0 " << doubleToString(shadowBlue);
@@ -116,10 +185,16 @@ void libvisio::VSDSVGGenerator::setStyle(const ::WPXPropertyList &propList, cons
m_outputSink << " 0 0 0 " << doubleToString(m_style["draw:shadow-opacity"]->getDouble()/m_style["draw:opacity"]->getDouble()) << " 0\"/>";
else
m_outputSink << " 0 0 0 " << doubleToString(m_style["draw:shadow-opacity"]->getDouble()) << " 0\"/>";
- m_outputSink << "<svg:feMerge><svg:feMergeNode in=\"offset-color\" /><svg:feMergeNode in=\"SourceGraphic\" /></svg:feMerge></svg:filter></svg:defs>";
+
+ m_outputSink << "<" << getNamespaceAndDelim() << "feMerge>";
+ m_outputSink << "<" << getNamespaceAndDelim() << "feMergeNode in=\"offset-color\" />";
+ m_outputSink << "<" << getNamespaceAndDelim() << "feMergeNode in=\"SourceGraphic\" />";
+ m_outputSink << "</" << getNamespaceAndDelim() << "feMerge>";
+ m_outputSink << "</" << getNamespaceAndDelim() << "filter>";
+ m_outputSink << "</" << getNamespaceAndDelim() << "defs>";
}
- if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "gradient")
+ if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "gradient" && m_style["draw:style"])
{
double angle = (m_style["draw:angle"] ? m_style["draw:angle"]->getDouble() : 0.0);
angle *= -1.0;
@@ -128,334 +203,520 @@ void libvisio::VSDSVGGenerator::setStyle(const ::WPXPropertyList &propList, cons
while(angle > 360)
angle -= 360;
- if (!m_gradient.count())
+ if (m_style["draw:style"]->getStr() == "radial" || m_style["draw:style"]->getStr() == "rectangular" ||
+ m_style["draw:style"]->getStr() == "square" || m_style["draw:style"]->getStr() == "ellipsoid")
{
- if (m_style["draw:style"] &&
- (m_style["draw:style"]->getStr() == "radial" ||
- m_style["draw:style"]->getStr() == "rectangular" ||
- m_style["draw:style"]->getStr() == "square" ||
- m_style["draw:style"]->getStr() == "ellipsoid"))
+ m_outputSink << "<" << getNamespaceAndDelim() << "defs>\n";
+ m_outputSink << " <" << getNamespaceAndDelim() << "radialGradient id=\"grad" << m_gradientIndex++ << "\"";
+
+ if (m_style["svg:cx"])
+ m_outputSink << " cx=\"" << m_style["svg:cx"]->getStr().cstr() << "\"";
+ else if (m_style["draw:cx"])
+ m_outputSink << " cx=\"" << m_style["draw:cx"]->getStr().cstr() << "\"";
+
+ if (m_style["svg:cy"])
+ m_outputSink << " cy=\"" << m_style["svg:cy"]->getStr().cstr() << "\"";
+ else if (m_style["draw:cy"])
+ m_outputSink << " cy=\"" << m_style["draw:cy"]->getStr().cstr() << "\"";
+ if (m_style["svg:r"])
+ m_outputSink << " r=\"" << m_style["svg:r"]->getStr().cstr() << "\"";
+ else if (m_style["draw:border"])
+ m_outputSink << " r=\"" << doubleToString((1 - m_style["draw:border"]->getDouble())*100.0) << "%\"";
+ else
+ m_outputSink << " r=\"100%\"";
+ m_outputSink << " >\n";
+ if (m_gradient.count())
{
- m_outputSink << "<svg:defs>\n";
- m_outputSink << " <svg:radialGradient id=\"grad" << m_gradientIndex++ << "\"";
-
- if (m_style["svg:cx"])
- m_outputSink << " cx=\"" << m_style["svg:cx"]->getStr().cstr() << "\"";
- else if (m_style["draw:cx"])
- m_outputSink << " cx=\"" << m_style["draw:cx"]->getStr().cstr() << "\"";
-
- if (m_style["svg:cy"])
- m_outputSink << " cy=\"" << m_style["svg:cy"]->getStr().cstr() << "\"";
- else if (m_style["draw:cy"])
- m_outputSink << " cy=\"" << m_style["draw:cy"]->getStr().cstr() << "\"";
- m_outputSink << " r=\"" << (1 - (m_style["draw:border"] ? m_style["draw:border"]->getDouble() : 0))*100.0 << "%\" >\n";
- m_outputSink << " >\n";
-
- if (m_style["draw:start-color"] && m_style["draw:end-color"])
+ for(unsigned c = 0; c < m_gradient.count(); c++)
{
- m_outputSink << " <svg:stop offset=\"0%\"";
- m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
-
- m_outputSink << " <svg:stop offset=\"100%\"";
- m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ WPXPropertyList const &grad=m_gradient[c];
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop";
+ if (grad["svg:offset"])
+ m_outputSink << " offset=\"" << grad["svg:offset"]->getStr().cstr() << "\"";
+ if (grad["svg:stop-color"])
+ m_outputSink << " stop-color=\"" << grad["svg:stop-color"]->getStr().cstr() << "\"";
+ if (grad["svg:stop-opacity"])
+ m_outputSink << " stop-opacity=\"" << doubleToString(grad["svg:stop-opacity"]->getDouble()) << "\"";
+ m_outputSink << "/>" << std::endl;
}
- m_outputSink << " </svg:radialGradient>\n";
- m_outputSink << "</svg:defs>\n";
}
- else if (m_style["draw:style"] && m_style["draw:style"]->getStr() == "linear")
+ else if (m_style["draw:start-color"] && m_style["draw:end-color"])
{
- m_outputSink << "<svg:defs>\n";
- m_outputSink << " <svg:linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"0%\"";
+ m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
- if (m_style["draw:start-color"] && m_style["draw:end-color"])
- {
- m_outputSink << " <svg:stop offset=\"0%\"";
- m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"100%\"";
+ m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ }
+ m_outputSink << " </" << getNamespaceAndDelim() << "radialGradient>\n";
+ m_outputSink << "</" << getNamespaceAndDelim() << "defs>\n";
+ }
+ else if (m_style["draw:style"]->getStr() == "linear" || m_style["draw:style"]->getStr() == "axial")
+ {
+ m_outputSink << "<" << getNamespaceAndDelim() << "defs>\n";
+ m_outputSink << " <" << getNamespaceAndDelim() << "linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
- m_outputSink << " <svg:stop offset=\"100%\"";
- m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ if (m_gradient.count())
+ {
+ bool canBuildAxial = false;
+ if (m_style["draw:style"]->getStr() == "axial")
+ {
+ // check if we can reconstruct the linear offset, ie. if each offset is a valid percent%
+ canBuildAxial = true;
+ for(unsigned c = 0; c < m_gradient.count(); ++c)
+ {
+ WPXPropertyList const &grad=m_gradient[c];
+ if (!grad["svg:offset"] || grad["svg:offset"]->getDouble()<0 || grad["svg:offset"]->getDouble() > 1)
+ {
+ canBuildAxial=false;
+ break;
+ }
+ WPXString str=grad["svg:offset"]->getStr();
+ int len=str.len();
+ if (len<1 || str.cstr()[len-1]!='%')
+ {
+ canBuildAxial=false;
+ break;
+ }
+ }
}
- m_outputSink << " </svg:linearGradient>\n";
-
- // not a simple horizontal gradient
- if(angle != 270)
+ if (canBuildAxial)
{
- m_outputSink << " <svg:linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
- m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
- m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
- m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
- m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
- m_outputSink << " </svg:linearGradient>\n";
+ for(unsigned c = m_gradient.count(); c>0 ; )
+ {
+ WPXPropertyList const &grad=m_gradient[--c];
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop ";
+ if (grad["svg:offset"])
+ m_outputSink << "offset=\"" << doubleToString(50.-50.*grad["svg:offset"]->getDouble()) << "%\"";
+ if (grad["svg:stop-color"])
+ m_outputSink << " stop-color=\"" << grad["svg:stop-color"]->getStr().cstr() << "\"";
+ if (grad["svg:stop-opacity"])
+ m_outputSink << " stop-opacity=\"" << doubleToString(grad["svg:stop-opacity"]->getDouble()) << "\"";
+ m_outputSink << "/>" << std::endl;
+ }
+ for(unsigned c = 0; c < m_gradient.count(); ++c)
+ {
+ WPXPropertyList const &grad=m_gradient[c];
+ if (c==0 && grad["svg:offset"] && grad["svg:offset"]->getDouble() <= 0)
+ continue;
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop ";
+ if (grad["svg:offset"])
+ m_outputSink << "offset=\"" << doubleToString(50.+50.*grad["svg:offset"]->getDouble()) << "%\"";
+ if (grad["svg:stop-color"])
+ m_outputSink << " stop-color=\"" << grad["svg:stop-color"]->getStr().cstr() << "\"";
+ if (grad["svg:stop-opacity"])
+ m_outputSink << " stop-opacity=\"" << doubleToString(grad["svg:stop-opacity"]->getDouble()) << "\"";
+ m_outputSink << "/>" << std::endl;
+ }
+ }
+ else
+ {
+ for(unsigned c = 0; c < m_gradient.count(); c++)
+ {
+ WPXPropertyList const &grad=m_gradient[c];
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop";
+ if (grad["svg:offset"])
+ m_outputSink << " offset=\"" << grad["svg:offset"]->getStr().cstr() << "\"";
+ if (grad["svg:stop-color"])
+ m_outputSink << " stop-color=\"" << grad["svg:stop-color"]->getStr().cstr() << "\"";
+ if (grad["svg:stop-opacity"])
+ m_outputSink << " stop-opacity=\"" << doubleToString(grad["svg:stop-opacity"]->getDouble()) << "\"";
+ m_outputSink << "/>" << std::endl;
+ }
}
-
- m_outputSink << "</svg:defs>\n";
}
- else if (m_style["draw:style"] && m_style["draw:style"]->getStr() == "axial")
+ else if (m_style["draw:start-color"] && m_style["draw:end-color"])
{
- m_outputSink << "<svg:defs>\n";
- m_outputSink << " <svg:linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
+ if (m_style["draw:style"]->getStr() == "linear")
+ {
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"0%\"";
+ m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
- if (m_style["draw:start-color"] && m_style["draw:end-color"])
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"100%\"";
+ m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ }
+ else
{
- m_outputSink << " <svg:stop offset=\"0%\"";
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"0%\"";
m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
- m_outputSink << " <svg:stop offset=\"50%\"";
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"50%\"";
m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
- m_outputSink << " <svg:stop offset=\"100%\"";
+ m_outputSink << " <" << getNamespaceAndDelim() << "stop offset=\"100%\"";
m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
- }
- m_outputSink << " </svg:linearGradient>\n";
-
- // not a simple horizontal gradient
- if(angle != 270)
- {
- m_outputSink << " <svg:linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
- m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
- m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
- m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
- m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
- m_outputSink << " </svg:linearGradient>\n";
+ m_outputSink << " stop-opacity=\"" << doubleToString(m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
}
+ }
+ m_outputSink << " </" << getNamespaceAndDelim() << "linearGradient>\n";
- m_outputSink << "</svg:defs>\n";
+ // not a simple horizontal gradient
+ if(angle != 270)
+ {
+ m_outputSink << " <" << getNamespaceAndDelim() << "linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
+ m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
+ m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
+ m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
+ m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
+ m_outputSink << " </" << getNamespaceAndDelim() << "linearGradient>\n";
}
+
+ m_outputSink << "</" << getNamespaceAndDelim() << "defs>\n";
}
+ }
+ else if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "bitmap" && m_style["draw:fill-image"] && m_style["libwpg:mime-type"])
+ {
+ m_outputSink << "<" << getNamespaceAndDelim() << "defs>\n";
+ m_outputSink << " <" << getNamespaceAndDelim() << "pattern id=\"img" << m_patternIndex++ << "\" patternUnits=\"userSpaceOnUse\" ";
+ if (m_style["svg:width"])
+ m_outputSink << "width=\"" << doubleToString(72*(m_style["svg:width"]->getDouble())) << "\" ";
else
- {
- if (m_style["draw:style"] && m_style["draw:style"]->getStr() == "radial")
- {
- m_outputSink << "<svg:defs>\n";
- m_outputSink << " <svg:radialGradient id=\"grad" << m_gradientIndex++ << "\" cx=\"" << m_style["svg:cx"]->getStr().cstr() << "\" cy=\"" << m_style["svg:cy"]->getStr().cstr() << "\" r=\"" << m_style["svg:r"]->getStr().cstr() << "\" >\n";
- for(unsigned c = 0; c < m_gradient.count(); c++)
- {
- m_outputSink << " <svg:stop offset=\"" << m_gradient[c]["svg:offset"]->getStr().cstr() << "\"";
+ m_outputSink << "width=\"100\" ";
- m_outputSink << " stop-color=\"" << m_gradient[c]["svg:stop-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << m_gradient[c]["svg:stop-opacity"]->getDouble() << "\" />" << std::endl;
+ if (m_style["svg:height"])
+ m_outputSink << "height=\"" << doubleToString(72*(m_style["svg:height"]->getDouble())) << "\">" << std::endl;
+ else
+ m_outputSink << "height=\"100\">" << std::endl;
+ m_outputSink << "<" << getNamespaceAndDelim() << "image ";
- }
- m_outputSink << " </svg:radialGradient>\n";
- m_outputSink << "</svg:defs>\n";
- }
- else
- {
- m_outputSink << "<svg:defs>\n";
- m_outputSink << " <svg:linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
- for(unsigned c = 0; c < m_gradient.count(); c++)
- {
- m_outputSink << " <svg:stop offset=\"" << m_gradient[c]["svg:offset"]->getStr().cstr() << "\"";
+ if (m_style["svg:x"])
+ m_outputSink << "x=\"" << doubleToString(72*(m_style["svg:x"]->getDouble())) << "\" ";
+ else
+ m_outputSink << "x=\"0\" ";
- m_outputSink << " stop-color=\"" << m_gradient[c]["svg:stop-color"]->getStr().cstr() << "\"";
- m_outputSink << " stop-opacity=\"" << m_gradient[c]["svg:stop-opacity"]->getDouble() << "\" />" << std::endl;
+ if (m_style["svg:y"])
+ m_outputSink << "y=\"" << doubleToString(72*(m_style["svg:y"]->getDouble())) << "\" ";
+ else
+ m_outputSink << "y=\"0\" ";
- }
- m_outputSink << " </svg:linearGradient>\n";
+ if (m_style["svg:width"])
+ m_outputSink << "width=\"" << doubleToString(72*(m_style["svg:width"]->getDouble())) << "\" ";
+ else
+ m_outputSink << "width=\"100\" ";
- // not a simple horizontal gradient
- if(angle != 270)
- {
- m_outputSink << " <svg:linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
- m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
- m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
- m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
- m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
- m_outputSink << " </svg:linearGradient>\n";
- }
+ if (m_style["svg:height"])
+ m_outputSink << "height=\"" << doubleToString(72*(m_style["svg:height"]->getDouble())) << "\" ";
+ else
+ m_outputSink << "height=\"100\" ";
- m_outputSink << "</svg:defs>\n";
- }
- }
+ m_outputSink << "xlink:href=\"data:" << m_style["libwpg:mime-type"]->getStr().cstr() << ";base64,";
+ m_outputSink << m_style["draw:fill-image"]->getStr().cstr();
+ m_outputSink << "\" />\n";
+ m_outputSink << " </" << getNamespaceAndDelim() << "pattern>\n";
+ m_outputSink << "</" << getNamespaceAndDelim() << "defs>\n";
}
- else if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "bitmap")
+
+ // check for arrow and if find some, define a basic arrow
+ if (m_style["draw:marker-start-path"])
{
- if (m_style["draw:fill-image"] && m_style["libwpg:mime-type"])
- {
- m_outputSink << "<svg:defs>\n";
- m_outputSink << " <svg:pattern id=\"img" << m_patternIndex++ << "\" patternUnits=\"userSpaceOnUse\" ";
- if (m_style["svg:width"])
- m_outputSink << "width=\"" << doubleToString(72*(m_style["svg:width"]->getDouble())) << "\" ";
- else
- m_outputSink << "width=\"100\" ";
+ m_outputSink << "<" << getNamespaceAndDelim() << "defs>\n";
+ m_outputSink << "<" << getNamespaceAndDelim() << "marker id=\"startMarker" << m_arrowStartIndex++ << "\" ";
+ m_outputSink << " markerUnits=\"strokeWidth\" orient=\"auto\" markerWidth=\"8\" markerHeight=\"6\"\n";
+ m_outputSink << " viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\">\n";
+ m_outputSink << "<" << getNamespaceAndDelim() << "polyline points=\"10,0 0,5 10,10 9,5\" fill=\"solid\" />\n";
+ m_outputSink << "</" << getNamespaceAndDelim() << "marker>\n";
+ m_outputSink << "</" << getNamespaceAndDelim() << "defs>\n";
+ }
+ if (m_style["draw:marker-end-path"])
+ {
+ m_outputSink << "<" << getNamespaceAndDelim() << "defs>\n";
+ m_outputSink << "<" << getNamespaceAndDelim() << "marker id=\"endMarker" << m_arrowEndIndex++ << "\" ";
+ m_outputSink << " markerUnits=\"strokeWidth\" orient=\"auto\" markerWidth=\"8\" markerHeight=\"6\"\n";
+ m_outputSink << " viewBox=\"0 0 10 10\" refX=\"1\" refY=\"5\">\n";
+ m_outputSink << "<" << getNamespaceAndDelim() << "polyline points=\"0,0 10,5 0,10 1,5\" fill=\"solid\" />\n";
+ m_outputSink << "</" << getNamespaceAndDelim() << "marker>\n";
+ m_outputSink << "</" << getNamespaceAndDelim() << "defs>\n";
+ }
+}
- if (m_style["svg:height"])
- m_outputSink << "height=\"" << doubleToString(72*(m_style["svg:height"]->getDouble())) << "\">" << std::endl;
- else
- m_outputSink << "height=\"100\">" << std::endl;
- m_outputSink << "<svg:image ";
+// create "style" attribute based on current pen and brush
+void VSDSVGGeneratorPrivate::writeStyle(bool /* isClosed */)
+{
+ m_outputSink << "style=\"";
- if (m_style["svg:x"])
- m_outputSink << "x=\"" << doubleToString(72*(m_style["svg:x"]->getDouble())) << "\" ";
- else
- m_outputSink << "x=\"0\" ";
+ double width = 1.0 / 72.0;
+ if (m_style["svg:stroke-width"])
+ {
+ width = m_style["svg:stroke-width"]->getDouble();
+#if 0
+ // add me in libmspub and libcdr
+ if (width <= 0.0 && m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() != "none")
+ width = 0.2 / 72.0; // reasonable hairline
+#endif
+ m_outputSink << "stroke-width: " << doubleToString(72*width) << "; ";
+ }
- if (m_style["svg:y"])
- m_outputSink << "y=\"" << doubleToString(72*(m_style["svg:y"]->getDouble())) << "\" ";
- else
- m_outputSink << "y=\"0\" ";
+ if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() != "none")
+ {
+ if (m_style["svg:stroke-color"])
+ m_outputSink << "stroke: " << m_style["svg:stroke-color"]->getStr().cstr() << "; ";
+ if(m_style["svg:stroke-opacity"] && m_style["svg:stroke-opacity"]->getInt()!= 1)
+ m_outputSink << "stroke-opacity: " << doubleToString(m_style["svg:stroke-opacity"]->getDouble()) << "; ";
+ }
- if (m_style["svg:width"])
- m_outputSink << "width=\"" << doubleToString(72*(m_style["svg:width"]->getDouble())) << "\" ";
+ if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() == "solid")
+ m_outputSink << "stroke-dasharray: none; ";
+ else if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() == "dash")
+ {
+ int dots1 = m_style["draw:dots1"] ? m_style["draw:dots1"]->getInt() : 0;
+ int dots2 = m_style["draw:dots2"] ? m_style["draw:dots2"]->getInt() : 0;
+ double dots1len = 72.*width, dots2len = 72.*width, gap = 72.*width;
+ std::string dots1lenUnit="", dots2lenUnit="", gapUnit="";
+ if (m_style["draw:dots1-length"])
+ {
+ dots1len = m_style["draw:dots1-length"]->getDouble();
+ std::string str = m_style["draw:dots1-length"]->getStr().cstr();
+ if (str.size() > 1 && str[str.size()-1]=='%')
+ {
+ dots1len *=100.;
+ dots1lenUnit="%";
+ }
else
- m_outputSink << "width=\"100\" ";
-
- if (m_style["svg:height"])
- m_outputSink << "height=\"" << doubleToString(72*(m_style["svg:height"]->getDouble())) << "\" ";
+ dots1len *=72.;
+ }
+ if (m_style["draw:dots2-length"])
+ {
+ dots2len = m_style["draw:dots2-length"]->getDouble();
+ std::string str = m_style["draw:dots2-length"]->getStr().cstr();
+ if (str.size() > 1 && str[str.size()-1]=='%')
+ {
+ dots2len *=100.;
+ dots2lenUnit="%";
+ }
else
- m_outputSink << "height=\"100\" ";
-
- m_outputSink << "xlink:href=\"data:" << m_style["libwpg:mime-type"]->getStr().cstr() << ";base64,";
- m_outputSink << m_style["draw:fill-image"]->getStr().cstr();
- m_outputSink << "\" />\n";
- m_outputSink << " </svg:pattern>\n";
- m_outputSink << "</svg:defs>\n";
+ dots2len *=72.;
+ }
+ if (m_style["draw:distance"])
+ {
+ gap = m_style["draw:distance"]->getDouble();
+ std::string str = m_style["draw:distance"]->getStr().cstr();
+ if (str.size() > 1 && str[str.size()-1]=='%')
+ {
+ gap *=100.;
+ gapUnit="%";
+ }
+ else
+ gap *=72.;
+ }
+ m_outputSink << "stroke-dasharray: ";
+ for (int i = 0; i < dots1; i++)
+ {
+ if (i)
+ m_outputSink << ", ";
+ m_outputSink << doubleToString(dots1len) << dots1lenUnit;
+ m_outputSink << ", ";
+ m_outputSink << doubleToString(gap) << gapUnit;
+ }
+ for (int j = 0; j < dots2; j++)
+ {
+ m_outputSink << ", ";
+ m_outputSink << doubleToString(dots2len) << dots2lenUnit;
+ m_outputSink << ", ";
+ m_outputSink << doubleToString(gap) << gapUnit;
}
+ m_outputSink << "; ";
}
+
+ if (m_style["svg:stroke-linecap"])
+ m_outputSink << "stroke-linecap: " << m_style["svg:stroke-linecap"]->getStr().cstr() << "; ";
+
+ if (m_style["svg:stroke-linejoin"])
+ m_outputSink << "stroke-linejoin: " << m_style["svg:stroke-linejoin"]->getStr().cstr() << "; ";
+
+ if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "none")
+ m_outputSink << "fill: none; ";
+ else if(m_style["svg:fill-rule"])
+ m_outputSink << "fill-rule: " << m_style["svg:fill-rule"]->getStr().cstr() << "; ";
+
+ if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "gradient")
+ m_outputSink << "fill: url(#grad" << m_gradientIndex-1 << "); ";
+ else if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "bitmap")
+ m_outputSink << "fill: url(#img" << m_patternIndex-1 << "); ";
+
+ if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible")
+ m_outputSink << "filter:url(#shadow" << m_shadowIndex-1 << "); ";
+
+ if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "solid")
+ if (m_style["draw:fill-color"])
+ m_outputSink << "fill: " << m_style["draw:fill-color"]->getStr().cstr() << "; ";
+ if(m_style["draw:opacity"] && m_style["draw:opacity"]->getDouble() < 1)
+ m_outputSink << "fill-opacity: " << doubleToString(m_style["draw:opacity"]->getDouble()) << "; ";
+
+ if (m_style["draw:marker-start-path"])
+ m_outputSink << "marker-start: url(#startMarker" << m_arrowStartIndex-1 << "); ";
+ if (m_style["draw:marker-end-path"])
+ m_outputSink << "marker-end: url(#endMarker" << m_arrowEndIndex-1 << "); ";
+
+ m_outputSink << "\""; // style
}
-void libvisio::VSDSVGGenerator::startLayer(const ::WPXPropertyList &propList)
+
+VSDSVGGenerator::VSDSVGGenerator(VSDStringVector &vec, const WPXString &nmSpace) :
+ m_pImpl(new VSDSVGGeneratorPrivate(vec, nmSpace))
{
- m_outputSink << "<svg:g";
- if (propList["svg:id"])
- m_outputSink << " id=\"Layer" << propList["svg:id"]->getInt() << "\"";
- if (propList["svg:fill-rule"])
- m_outputSink << " fill-rule=\"" << propList["svg:fill-rule"]->getStr().cstr() << "\"";
- m_outputSink << " >\n";
}
-void libvisio::VSDSVGGenerator::endLayer()
+VSDSVGGenerator::~VSDSVGGenerator()
{
- m_outputSink << "</svg:g>\n";
+ delete m_pImpl;
}
-void libvisio::VSDSVGGenerator::drawRectangle(const ::WPXPropertyList &propList)
+void VSDSVGGenerator::startGraphics(const WPXPropertyList &propList)
{
- m_outputSink << "<svg:rect ";
- m_outputSink << "x=\"" << doubleToString(72*propList["svg:x"]->getDouble()) << "\" y=\"" << doubleToString(72*propList["svg:y"]->getDouble()) << "\" ";
- m_outputSink << "width=\"" << doubleToString(72*propList["svg:width"]->getDouble()) << "\" height=\"" << doubleToString(72*propList["svg:height"]->getDouble()) << "\" ";
- if((propList["svg:rx"] && propList["svg:rx"]->getInt() !=0) || (propList["svg:ry"] && propList["svg:ry"]->getInt() !=0))
- m_outputSink << "rx=\"" << doubleToString(72*propList["svg:rx"]->getDouble()) << "\" ry=\"" << doubleToString(72*propList["svg:ry"]->getDouble()) << "\" ";
- writeStyle();
- m_outputSink << "/>\n";
+ if (m_pImpl->m_nmSpace.empty())
+ {
+ m_pImpl->m_outputSink << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
+ m_pImpl->m_outputSink << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"";
+ m_pImpl->m_outputSink << " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
+ }
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "svg version=\"1.1\" xmlns";
+ m_pImpl->m_outputSink << (m_pImpl->m_nmSpace.empty() ? "" : ":") << m_pImpl->m_nmSpace << "=\"http://www.w3.org/2000/svg\" ";
+ m_pImpl->m_outputSink << "xmlns:xlink=\"http://www.w3.org/1999/xlink\" ";
+ if (propList["svg:width"])
+ m_pImpl->m_outputSink << "width=\"" << doubleToString(72*(propList["svg:width"]->getDouble())) << "\" ";
+ if (propList["svg:height"])
+ m_pImpl->m_outputSink << "height=\"" << doubleToString(72*(propList["svg:height"]->getDouble())) << "\"";
+ m_pImpl->m_outputSink << " >\n";
}
-void libvisio::VSDSVGGenerator::drawEllipse(const WPXPropertyList &propList)
+void VSDSVGGenerator::endGraphics()
{
- m_outputSink << "<svg:ellipse ";
- m_outputSink << "cx=\"" << doubleToString(72*propList["svg:cx"]->getDouble()) << "\" cy=\"" << doubleToString(72*propList["svg:cy"]->getDouble()) << "\" ";
- m_outputSink << "rx=\"" << doubleToString(72*propList["svg:rx"]->getDouble()) << "\" ry=\"" << doubleToString(72*propList["svg:ry"]->getDouble()) << "\" ";
- writeStyle();
- if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
- m_outputSink << " transform=\" rotate(" << doubleToString(-propList["libwpg:rotate"]->getDouble())
- << ", " << doubleToString(72*propList["svg:cy"]->getDouble())
- << ", " << doubleToString(72*propList["svg:cy"]->getDouble())
- << ")\" ";
- m_outputSink << "/>\n";
+ m_pImpl->m_outputSink << "</" << m_pImpl->getNamespaceAndDelim() << "svg>\n";
+ m_pImpl->m_vec.append(m_pImpl->m_outputSink.str().c_str());
+ m_pImpl->m_outputSink.str("");
}
-void libvisio::VSDSVGGenerator::drawPolyline(const ::WPXPropertyListVector &vertices)
+
+void VSDSVGGenerator::startLayer(const ::WPXPropertyList &propList)
{
- drawPolySomething(vertices, false);
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "g";
+ if (propList["svg:id"])
+ m_pImpl->m_outputSink << " id=\"Layer" << propList["svg:id"]->getStr().cstr() << "\"";
+ else
+ m_pImpl->m_outputSink << " id=\"Layer" << m_pImpl->m_layerId++ << "\"";
+ if (propList["svg:fill-rule"])
+ m_pImpl->m_outputSink << " fill-rule=\"" << propList["svg:fill-rule"]->getStr().cstr() << "\"";
+ m_pImpl->m_outputSink << " >\n";
}
-void libvisio::VSDSVGGenerator::drawPolygon(const ::WPXPropertyListVector &vertices)
+void VSDSVGGenerator::endLayer()
{
- drawPolySomething(vertices, true);
+ m_pImpl->m_outputSink << "</" << m_pImpl->getNamespaceAndDelim() << "g>\n";
}
-void libvisio::VSDSVGGenerator::drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed)
+void VSDSVGGenerator::setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &gradient)
{
- if(vertices.count() < 2)
+ m_pImpl->setStyle(propList, gradient);
+}
+
+void VSDSVGGenerator::drawRectangle(const ::WPXPropertyList &propList)
+{
+ if (!propList["svg:x"] || !propList["svg:y"] || !propList["svg:width"] || !propList["svg:height"])
return;
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "rect ";
+ m_pImpl->m_outputSink << "x=\"" << doubleToString(72*propList["svg:x"]->getDouble()) << "\" y=\"" << doubleToString(72*propList["svg:y"]->getDouble()) << "\" ";
+ m_pImpl->m_outputSink << "width=\"" << doubleToString(72*propList["svg:width"]->getDouble()) << "\" height=\"" << doubleToString(72*propList["svg:height"]->getDouble()) << "\" ";
+ if(propList["svg:rx"] && propList["svg:rx"]->getDouble() > 0 && propList["svg:ry"] && propList["svg:ry"]->getDouble()>0)
+ m_pImpl->m_outputSink << "rx=\"" << doubleToString(72*propList["svg:rx"]->getDouble()) << "\" ry=\"" << doubleToString(72*propList["svg:ry"]->getDouble()) << "\" ";
+ m_pImpl->writeStyle();
+ m_pImpl->m_outputSink << "/>\n";
+}
- if(vertices.count() == 2)
- {
- m_outputSink << "<svg:line ";
- m_outputSink << "x1=\"" << doubleToString(72*(vertices[0]["svg:x"]->getDouble())) << "\" y1=\"" << doubleToString(72*(vertices[0]["svg:y"]->getDouble())) << "\" ";
- m_outputSink << "x2=\"" << doubleToString(72*(vertices[1]["svg:x"]->getDouble())) << "\" y2=\"" << doubleToString(72*(vertices[1]["svg:y"]->getDouble())) << "\"\n";
- writeStyle();
- m_outputSink << "/>\n";
- }
- else
- {
- if (isClosed)
- m_outputSink << "<svg:polygon ";
- else
- m_outputSink << "<svg:polyline ";
+void VSDSVGGenerator::drawEllipse(const WPXPropertyList &propList)
+{
+ if (!propList["svg:cx"] || !propList["svg:cy"] || !propList["svg:rx"] || !propList["svg:ry"])
+ return;
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "ellipse ";
+ m_pImpl->m_outputSink << "cx=\"" << doubleToString(72*propList["svg:cx"]->getDouble()) << "\" cy=\"" << doubleToString(72*propList["svg:cy"]->getDouble()) << "\" ";
+ m_pImpl->m_outputSink << "rx=\"" << doubleToString(72*propList["svg:rx"]->getDouble()) << "\" ry=\"" << doubleToString(72*propList["svg:ry"]->getDouble()) << "\" ";
+ m_pImpl->writeStyle();
+ if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
+ m_pImpl->m_outputSink << " transform=\" rotate(" << doubleToString(-propList["libwpg:rotate"]->getDouble())
+ << ", " << doubleToString(72*propList["svg:cy"]->getDouble())
+ << ", " << doubleToString(72*propList["svg:cy"]->getDouble())
+ << ")\" ";
+ m_pImpl->m_outputSink << "/>\n";
+}
- m_outputSink << "points=\"";
- for(unsigned i = 0; i < vertices.count(); i++)
- {
- m_outputSink << doubleToString(72*(vertices[i]["svg:x"]->getDouble())) << " " << doubleToString(72*(vertices[i]["svg:y"]->getDouble()));
- if (i < vertices.count()-1)
- m_outputSink << ", ";
- }
- m_outputSink << "\"\n";
- writeStyle(isClosed);
- m_outputSink << "/>\n";
- }
+void VSDSVGGenerator::drawPolyline(const ::WPXPropertyListVector &vertices)
+{
+ m_pImpl->drawPolySomething(vertices, false);
}
-void libvisio::VSDSVGGenerator::drawPath(const ::WPXPropertyListVector &path)
+void VSDSVGGenerator::drawPolygon(const ::WPXPropertyListVector &vertices)
{
- m_outputSink << "<svg:path d=\" ";
+ m_pImpl->drawPolySomething(vertices, true);
+}
+
+void VSDSVGGenerator::drawPath(const ::WPXPropertyListVector &path)
+{
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "path d=\" ";
bool isClosed = false;
unsigned i=0;
for(i=0; i < path.count(); i++)
{
WPXPropertyList propList = path[i];
- if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "M")
+ if (!propList["libwpg:path-action"]) continue;
+ std::string action=propList["libwpg:path-action"]->getStr().cstr();
+ if (action.length()!=1) continue;
+ bool coordOk=propList["svg:x"]&&propList["svg:y"];
+ bool coord1Ok=coordOk && propList["svg:x1"]&&propList["svg:y1"];
+ bool coord2Ok=coord1Ok && propList["svg:x2"]&&propList["svg:y2"];
+ if (propList["svg:x"] && action[0] == 'H')
+ m_pImpl->m_outputSink << "\nH" << doubleToString(72*(propList["svg:x"]->getDouble()));
+ else if (propList["svg:y"] && action[0] == 'V')
+ m_pImpl->m_outputSink << "\nV" << doubleToString(72*(propList["svg:y"]->getDouble()));
+ else if (coordOk && (action[0] == 'M' || action[0] == 'L' || action[0] == 'T'))
{
- m_outputSink << "\nM";
- m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
+ m_pImpl->m_outputSink << "\n" << action;
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
}
- else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "L")
+ else if (coord1Ok && (action[0] == 'Q' || action[0] == 'S'))
{
- m_outputSink << "\nL";
- m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
+ m_pImpl->m_outputSink << "\n" << action;
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x1"]->getDouble())) << "," << doubleToString(72*(propList["svg:y1"]->getDouble())) << " ";
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
}
- else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "C")
+ else if (coord2Ok && action[0] == 'C')
{
- m_outputSink << "\nC";
- m_outputSink << doubleToString(72*(propList["svg:x1"]->getDouble())) << "," << doubleToString(72*(propList["svg:y1"]->getDouble())) << " ";
- m_outputSink << doubleToString(72*(propList["svg:x2"]->getDouble())) << "," << doubleToString(72*(propList["svg:y2"]->getDouble())) << " ";
- m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
+ m_pImpl->m_outputSink << "\nC";
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x1"]->getDouble())) << "," << doubleToString(72*(propList["svg:y1"]->getDouble())) << " ";
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x2"]->getDouble())) << "," << doubleToString(72*(propList["svg:y2"]->getDouble())) << " ";
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
}
- else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "A")
+ else if (coordOk && propList["svg:rx"] && propList["svg:ry"] && action[0] == 'A')
{
- m_outputSink << "\nA";
- m_outputSink << doubleToString(72*(propList["svg:rx"]->getDouble())) << "," << doubleToString(72*(propList["svg:ry"]->getDouble())) << " ";
- m_outputSink << doubleToString(propList["libwpg:rotate"] ? propList["libwpg:rotate"]->getDouble() : 0) << " ";
- m_outputSink << (propList["libwpg:large-arc"] ? propList["libwpg:large-arc"]->getInt() : 1) << ",";
- m_outputSink << (propList["libwpg:sweep"] ? propList["libwpg:sweep"]->getInt() : 1) << " ";
- m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
+ m_pImpl->m_outputSink << "\nA";
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:rx"]->getDouble())) << "," << doubleToString(72*(propList["svg:ry"]->getDouble())) << " ";
+ m_pImpl->m_outputSink << doubleToString(propList["libwpg:rotate"] ? propList["libwpg:rotate"]->getDouble() : 0) << " ";
+ m_pImpl->m_outputSink << (propList["libwpg:large-arc"] ? propList["libwpg:large-arc"]->getInt() : 1) << ",";
+ m_pImpl->m_outputSink << (propList["libwpg:sweep"] ? propList["libwpg:sweep"]->getInt() : 1) << " ";
+ m_pImpl->m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
}
- else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "Z")
+ else if (action[0] == 'Z' )
{
isClosed = true;
- m_outputSink << "\nZ";
+ m_pImpl->m_outputSink << "\nZ";
}
}
- m_outputSink << "\" \n";
- writeStyle(isClosed);
- m_outputSink << "/>\n";
+ m_pImpl->m_outputSink << "\" \n";
+ m_pImpl->writeStyle(isClosed);
+ m_pImpl->m_outputSink << "/>\n";
}
-void libvisio::VSDSVGGenerator::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData &binaryData)
+void VSDSVGGenerator::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData &binaryData)
{
if (!propList["libwpg:mime-type"] || propList["libwpg:mime-type"]->getStr().len() <= 0)
return;
WPXString base64 = binaryData.getBase64Data();
- m_outputSink << "<svg:image ";
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "image ";
if (propList["svg:x"] && propList["svg:y"] && propList["svg:width"] && propList["svg:height"])
{
double x(propList["svg:x"]->getDouble());
@@ -465,37 +726,40 @@ void libvisio::VSDSVGGenerator::drawGraphicObject(const ::WPXPropertyList &propL
bool flipX(propList["draw:mirror-horizontal"] && propList["draw:mirror-horizontal"]->getInt());
bool flipY(propList["draw:mirror-vertical"] && propList["draw:mirror-vertical"]->getInt());
- double xmiddle = x + width / 2.0;
- double ymiddle = y + height / 2.0;
- m_outputSink << "x=\"" << doubleToString(72*x) << "\" y=\"" << doubleToString(72*y) << "\" ";
- m_outputSink << "width=\"" << doubleToString(72*width) << "\" height=\"" << doubleToString(72*height) << "\" ";
- m_outputSink << "transform=\"";
- m_outputSink << " translate(" << doubleToString(72*xmiddle) << ", " << doubleToString (72*ymiddle) << ") ";
- m_outputSink << " scale(" << (flipX ? "-1" : "1") << ", " << (flipY ? "-1" : "1") << ") ";
- // rotation is around the center of the object's bounding box
- if (propList["libwpg:rotate"])
+ m_pImpl->m_outputSink << "x=\"" << doubleToString(72*x) << "\" y=\"" << doubleToString(72*y) << "\" ";
+ m_pImpl->m_outputSink << "width=\"" << doubleToString(72*width) << "\" height=\"" << doubleToString(72*height) << "\" ";
+ if (flipX || flipY || propList["libwpg:rotate"])
{
- double angle(propList["libwpg:rotate"]->getDouble());
- while (angle > 180.0)
- angle -= 360.0;
- while (angle < -180.0)
- angle += 360.0;
- m_outputSink << " rotate(" << doubleToString(angle) << ") ";
+ double xmiddle = x + width / 2.0;
+ double ymiddle = y + height / 2.0;
+ m_pImpl->m_outputSink << "transform=\"";
+ m_pImpl->m_outputSink << " translate(" << doubleToString(72*xmiddle) << ", " << doubleToString (72*ymiddle) << ") ";
+ m_pImpl->m_outputSink << " scale(" << (flipX ? "-1" : "1") << ", " << (flipY ? "-1" : "1") << ") ";
+ // rotation is around the center of the object's bounding box
+ if (propList["libwpg:rotate"])
+ {
+ double angle(propList["libwpg:rotate"]->getDouble());
+ while (angle > 180.0)
+ angle -= 360.0;
+ while (angle < -180.0)
+ angle += 360.0;
+ m_pImpl->m_outputSink << " rotate(" << doubleToString(angle) << ") ";
+ }
+ m_pImpl->m_outputSink << " translate(" << doubleToString(-72*xmiddle) << ", " << doubleToString (-72*ymiddle) << ") ";
+ m_pImpl->m_outputSink << "\" ";
}
- m_outputSink << " translate(" << doubleToString(-72*xmiddle) << ", " << doubleToString (-72*ymiddle) << ") ";
- m_outputSink << "\" ";
}
- m_outputSink << "xlink:href=\"data:" << propList["libwpg:mime-type"]->getStr().cstr() << ";base64,";
- m_outputSink << base64.cstr();
- m_outputSink << "\" />\n";
+ m_pImpl->m_outputSink << "xlink:href=\"data:" << propList["libwpg:mime-type"]->getStr().cstr() << ";base64,";
+ m_pImpl->m_outputSink << base64.cstr();
+ m_pImpl->m_outputSink << "\" />\n";
}
-void libvisio::VSDSVGGenerator::startTextObject(const ::WPXPropertyList &propList, const ::WPXPropertyListVector & /* path */)
+void VSDSVGGenerator::startTextObject(const ::WPXPropertyList &propList, const ::WPXPropertyListVector & /* path */)
{
double x = 0.0;
double y = 0.0;
double height = 0.0;
- m_outputSink << "<svg:text ";
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "text ";
if (propList["svg:x"] && propList["svg:y"])
{
x = propList["svg:x"]->getDouble();
@@ -534,7 +798,7 @@ void libvisio::VSDSVGGenerator::startTextObject(const ::WPXPropertyList &propLis
if (propList["fo:padding-left"])
x += propList["fo:padding-left"]->getDouble();
- m_outputSink << "x=\"" << doubleToString(72*x) << "\" y=\"" << doubleToString(72*y) << "\"";
+ m_pImpl->m_outputSink << "x=\"" << doubleToString(72*x) << "\" y=\"" << doubleToString(72*y) << "\"";
// rotation is around the center of the object's bounding box
if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
@@ -544,121 +808,52 @@ void libvisio::VSDSVGGenerator::startTextObject(const ::WPXPropertyList &propLis
angle -= 360.0;
while (angle < -180.0)
angle += 360.0;
- m_outputSink << " transform=\"rotate(" << doubleToString(angle) << ", " << doubleToString(72*xmiddle) << ", " << doubleToString(72*ymiddle) << ")\" ";
+ m_pImpl->m_outputSink << " transform=\"rotate(" << doubleToString(angle) << ", " << doubleToString(72*xmiddle) << ", " << doubleToString(72*ymiddle) << ")\" ";
}
- m_outputSink << ">\n";
+ m_pImpl->m_outputSink << ">\n";
}
-void libvisio::VSDSVGGenerator::endTextObject()
+void VSDSVGGenerator::endTextObject()
{
- m_outputSink << "</svg:text>\n";
+ m_pImpl->m_outputSink << "</" << m_pImpl->getNamespaceAndDelim() << "text>\n";
}
-void libvisio::VSDSVGGenerator::startTextSpan(const ::WPXPropertyList &propList)
+void VSDSVGGenerator::startTextSpan(const ::WPXPropertyList &propList)
{
- m_outputSink << "<svg:tspan ";
+ m_pImpl->m_outputSink << "<" << m_pImpl->getNamespaceAndDelim() << "tspan ";
if (propList["style:font-name"])
- m_outputSink << "font-family=\"" << propList["style:font-name"]->getStr().cstr() << "\" ";
+ m_pImpl->m_outputSink << "font-family=\"" << propList["style:font-name"]->getStr().cstr() << "\" ";
if (propList["fo:font-style"])
- m_outputSink << "font-style=\"" << propList["fo:font-style"]->getStr().cstr() << "\" ";
+ m_pImpl->m_outputSink << "font-style=\"" << propList["fo:font-style"]->getStr().cstr() << "\" ";
if (propList["fo:font-weight"])
- m_outputSink << "font-weight=\"" << propList["fo:font-weight"]->getStr().cstr() << "\" ";
+ m_pImpl->m_outputSink << "font-weight=\"" << propList["fo:font-weight"]->getStr().cstr() << "\" ";
if (propList["fo:font-variant"])
- m_outputSink << "font-variant=\"" << propList["fo:font-variant"]->getStr().cstr() << "\" ";
+ m_pImpl->m_outputSink << "font-variant=\"" << propList["fo:font-variant"]->getStr().cstr() << "\" ";
if (propList["fo:font-size"])
- m_outputSink << "font-size=\"" << doubleToString(propList["fo:font-size"]->getDouble()) << "\" ";
+ m_pImpl->m_outputSink << "font-size=\"" << doubleToString(propList["fo:font-size"]->getDouble()) << "\" ";
if (propList["fo:color"])
- m_outputSink << "fill=\"" << propList["fo:color"]->getStr().cstr() << "\" ";
+ m_pImpl->m_outputSink << "fill=\"" << propList["fo:color"]->getStr().cstr() << "\" ";
if (propList["fo:text-transform"])
- m_outputSink << "text-transform=\"" << propList["fo:text-transform"]->getStr().cstr() << "\" ";
+ m_pImpl->m_outputSink << "text-transform=\"" << propList["fo:text-transform"]->getStr().cstr() << "\" ";
if (propList["svg:fill-opacity"])
- m_outputSink << "fill-opacity=\"" << doubleToString(propList["svg:fill-opacity"]->getDouble()) << "\" ";
+ m_pImpl->m_outputSink << "fill-opacity=\"" << doubleToString(propList["svg:fill-opacity"]->getDouble()) << "\" ";
if (propList["svg:stroke-opacity"])
- m_outputSink << "stroke-opacity=\"" << doubleToString(propList["svg:stroke-opacity"]->getDouble()) << "\" ";
- m_outputSink << ">\n";
+ m_pImpl->m_outputSink << "stroke-opacity=\"" << doubleToString(propList["svg:stroke-opacity"]->getDouble()) << "\" ";
+ m_pImpl->m_outputSink << ">\n";
}
-void libvisio::VSDSVGGenerator::endTextSpan()
+void VSDSVGGenerator::endTextSpan()
{
- m_outputSink << "</svg:tspan>\n";
+ m_pImpl->m_outputSink << "</" << m_pImpl->getNamespaceAndDelim() << "tspan>\n";
}
-void libvisio::VSDSVGGenerator::insertText(const ::WPXString &str)
+void VSDSVGGenerator::insertText(const ::WPXString &str)
{
WPXString tempUTF8(str, true);
- m_outputSink << tempUTF8.cstr() << "\n";
+ m_pImpl->m_outputSink << tempUTF8.cstr() << "\n";
}
-// create "style" attribute based on current pen and brush
-void libvisio::VSDSVGGenerator::writeStyle(bool /* isClosed */)
-{
- m_outputSink << "style=\"";
-
- if (m_style["svg:stroke-width"])
- m_outputSink << "stroke-width: " << doubleToString(72*m_style["svg:stroke-width"]->getDouble()) << "; ";
-
- if ((m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() != "none"))
- {
- if (m_style["svg:stroke-color"])
- m_outputSink << "stroke: " << m_style["svg:stroke-color"]->getStr().cstr() << "; ";
- if(m_style["svg:stroke-opacity"] && m_style["svg:stroke-opacity"]->getInt()!= 1)
- m_outputSink << "stroke-opacity: " << doubleToString(m_style["svg:stroke-opacity"]->getDouble()) << "; ";
- }
-
- if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() == "solid")
- m_outputSink << "stroke-dasharray: solid; ";
- else if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() == "dash")
- {
- int dots1 = m_style["draw:dots1"]->getInt();
- int dots2 = m_style["draw:dots2"]->getInt();
- double dots1len = m_style["draw:dots1-length"]->getDouble();
- double dots2len = m_style["draw:dots2-length"]->getDouble();
- double gap = m_style["draw:distance"]->getDouble();
- m_outputSink << "stroke-dasharray: ";
- for (int i = 0; i < dots1; i++)
- {
- if (i)
- m_outputSink << ", ";
- m_outputSink << (int)dots1len;
- m_outputSink << ", ";
- m_outputSink << (int)gap;
- }
- for (int j = 0; j < dots2; j++)
- {
- m_outputSink << ", ";
- m_outputSink << (int)dots2len;
- m_outputSink << ", ";
- m_outputSink << (int)gap;
- }
- m_outputSink << "; ";
- }
-
- if (m_style["svg:stroke-linecap"])
- m_outputSink << "stroke-linecap: " << m_style["svg:stroke-linecap"]->getStr().cstr() << "; ";
-
- if (m_style["svg:stroke-linejoin"])
- m_outputSink << "stroke-linejoin: " << m_style["svg:stroke-linejoin"]->getStr().cstr() << "; ";
-
- if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "none")
- m_outputSink << "fill: none; ";
- else if(m_style["svg:fill-rule"])
- m_outputSink << "fill-rule: " << m_style["svg:fill-rule"]->getStr().cstr() << "; ";
-
- if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "gradient")
- m_outputSink << "fill: url(#grad" << m_gradientIndex-1 << "); ";
+} // namespace libvisio
- if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "bitmap")
- m_outputSink << "fill: url(#img" << m_patternIndex-1 << "); ";
-
- if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible")
- m_outputSink << "filter:url(#shadow" << m_shadowIndex-1 << "); ";
-
- if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "solid")
- if (m_style["draw:fill-color"])
- m_outputSink << "fill: " << m_style["draw:fill-color"]->getStr().cstr() << "; ";
- if(m_style["draw:opacity"] && m_style["draw:opacity"]->getDouble() < 1)
- m_outputSink << "fill-opacity: " << doubleToString(m_style["draw:opacity"]->getDouble()) << "; ";
- m_outputSink << "\""; // style
-}
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
diff --git a/src/lib/VSDSVGGenerator.h b/src/lib/VSDSVGGenerator.h
index 1f35e4e..d9106b5 100644
--- a/src/lib/VSDSVGGenerator.h
+++ b/src/lib/VSDSVGGenerator.h
@@ -40,11 +40,12 @@
namespace libvisio
{
+struct VSDSVGGeneratorPrivate;
class VSDSVGGenerator : public libwpg::WPGPaintInterface
{
public:
- VSDSVGGenerator(VSDStringVector &vec);
+ VSDSVGGenerator(VSDStringVector &vec, const WPXString &nmspace="svg");
~VSDSVGGenerator();
void startGraphics(const ::WPXPropertyList &propList);
@@ -71,16 +72,9 @@ public:
void insertText(const ::WPXString &str);
private:
- ::WPXPropertyListVector m_gradient;
- ::WPXPropertyList m_style;
- int m_gradientIndex;
- int m_patternIndex;
- int m_shadowIndex;
- void writeStyle(bool isClosed=true);
- void drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed);
-
- std::ostringstream m_outputSink;
- VSDStringVector &m_vec;
+ VSDSVGGenerator(const VSDSVGGenerator &);
+ VSDSVGGenerator &operator=(const VSDSVGGenerator &);
+ VSDSVGGeneratorPrivate *m_pImpl;
};
} // namespace libvisio