Initial svg support.
This commit is contained in:
parent
101bfb4207
commit
65ac927929
22 changed files with 284 additions and 30 deletions
|
@ -9,6 +9,8 @@ list(APPEND publishing_HEADERS
|
|||
pdf/PdfStream.h
|
||||
pdf/PdfXRefTable.h
|
||||
pdf/PdfWriter.h
|
||||
plotting/GraphPlotter.h
|
||||
plotting/SvgConverter.h
|
||||
)
|
||||
|
||||
list(APPEND publishing_LIB_INCLUDES
|
||||
|
@ -22,6 +24,8 @@ list(APPEND publishing_LIB_INCLUDES
|
|||
pdf/PdfStream.cpp
|
||||
pdf/PdfXRefTable.cpp
|
||||
pdf/PdfWriter.cpp
|
||||
plotting/GraphPlotter.h
|
||||
plotting/SvgConverter.h
|
||||
DocumentConverter.cpp
|
||||
)
|
||||
|
||||
|
@ -32,6 +36,6 @@ target_include_directories(publishing PUBLIC
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/pdf"
|
||||
)
|
||||
set_target_properties( publishing PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||
target_link_libraries( publishing PUBLIC core web)
|
||||
target_link_libraries( publishing PUBLIC core web graphics visual_elements)
|
||||
|
||||
set_property(TARGET publishing PROPERTY FOLDER src)
|
0
src/publishing/plotting/GraphPlotter.cpp
Normal file
0
src/publishing/plotting/GraphPlotter.cpp
Normal file
0
src/publishing/plotting/GraphPlotter.h
Normal file
0
src/publishing/plotting/GraphPlotter.h
Normal file
0
src/publishing/plotting/SvgConverter.cpp
Normal file
0
src/publishing/plotting/SvgConverter.cpp
Normal file
0
src/publishing/plotting/SvgConverter.h
Normal file
0
src/publishing/plotting/SvgConverter.h
Normal file
|
@ -27,6 +27,11 @@ list(APPEND web_LIB_INCLUDES
|
|||
html/elements/HtmlHeadElement.cpp
|
||||
html/elements/HtmlBodyElement.cpp
|
||||
html/elements/HtmlParagraphElement.cpp
|
||||
svg/SvgDocument.cpp
|
||||
svg/SvgWriter.cpp
|
||||
svg/SvgShapeElement.cpp
|
||||
svg/SvgElement.cpp
|
||||
svg/elements/SvgShapeElements.cpp
|
||||
)
|
||||
|
||||
# add the executable
|
||||
|
@ -34,6 +39,8 @@ add_library(${MODULE_NAME} SHARED ${web_LIB_INCLUDES})
|
|||
|
||||
target_include_directories(web PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/svg/elements
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xml
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xml/xml-elements
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/html
|
||||
|
@ -41,5 +48,5 @@ target_include_directories(web PUBLIC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/markdown
|
||||
)
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)
|
||||
target_link_libraries(${MODULE_NAME} PUBLIC core compiler)
|
||||
target_link_libraries(${MODULE_NAME} PUBLIC core compiler geometry)
|
||||
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
|
@ -5,9 +5,8 @@ std::string HtmlParagraphElement::toString(unsigned depth, bool keepInline) cons
|
|||
const auto prefix = std::string(2*depth, ' ');
|
||||
|
||||
auto content = prefix + "<" + getTagName();
|
||||
for (std::size_t idx=0; idx< getNumAttributes(); idx++)
|
||||
for (const auto& [key, attribute] : getAttributes())
|
||||
{
|
||||
auto attribute = getAttribute(idx);
|
||||
content += " " + attribute->getName() + "=\"" + attribute->getValue() + "\"";
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#include "SvgDocument.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
SvgDocument::SvgDocument()
|
||||
: XmlDocument()
|
||||
{
|
||||
auto root = XmlElement::Create("svg");
|
||||
|
||||
auto xmlns = std::make_unique<XmlAttribute>("xmlns");
|
||||
xmlns->setValue("http://www.w3.org/2000/svg");
|
||||
|
||||
root->addAttribute(std::move(xmlns));
|
||||
|
||||
setRoot(std::move(root));
|
||||
}
|
||||
|
||||
void SvgDocument::setViewBox(unsigned x, unsigned y, unsigned w, unsigned h)
|
||||
{
|
||||
auto viewbox = std::make_unique<XmlAttribute>("viewBox");
|
||||
std::stringstream sstr;
|
||||
sstr << x << " " << y << " " << w << " " << h;
|
||||
viewbox->setValue(sstr.str());
|
||||
|
||||
getRoot()->addAttribute(std::move(viewbox));
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "XmlDocument.h"
|
||||
|
||||
class SvgDocument : public XmlDocument
|
||||
{
|
||||
public:
|
||||
SvgDocument();
|
||||
void setViewBox(unsigned x, unsigned y, unsigned w, unsigned h);
|
||||
};
|
7
src/web/svg/SvgElement.cpp
Normal file
7
src/web/svg/SvgElement.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "SvgElement.h"
|
||||
|
||||
SvgElement::SvgElement(const std::string& tagName)
|
||||
: XmlElement(tagName)
|
||||
{
|
||||
|
||||
}
|
9
src/web/svg/SvgElement.h
Normal file
9
src/web/svg/SvgElement.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "XmlElement.h"
|
||||
|
||||
class SvgElement : public XmlElement
|
||||
{
|
||||
public:
|
||||
SvgElement(const std::string& tagName);
|
||||
};
|
41
src/web/svg/SvgShapeElement.cpp
Normal file
41
src/web/svg/SvgShapeElement.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "SvgShapeElement.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
SvgShapeElement::SvgShapeElement(const std::string& tagName)
|
||||
: SvgElement(tagName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgShapeElement::setFill(const Color& fill)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("fill");
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "rgb(" << fill.getR() << "," << fill.getG() << "," << fill.getB() << ")";
|
||||
attr->setValue(sstr.str());
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setStrokeWidth(unsigned width)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("stroke-width");
|
||||
attr->setValue(std::to_string(width));
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setStrokeColor(const Color& stroke)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("stroke");
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "rgb(" << stroke.getR() << "," << stroke.getG() << "," << stroke.getB() << ")";
|
||||
attr->setValue(sstr.str());
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
17
src/web/svg/SvgShapeElement.h
Normal file
17
src/web/svg/SvgShapeElement.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "SvgElement.h"
|
||||
#include "Color.h"
|
||||
|
||||
class SvgShapeElement : public SvgElement
|
||||
{
|
||||
public:
|
||||
SvgShapeElement(const std::string& tagName);
|
||||
|
||||
void setFill(const Color& fill);
|
||||
|
||||
void setStrokeWidth(unsigned width);
|
||||
|
||||
void setStrokeColor(const Color& stroke);
|
||||
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
#include "SvgWriter.h"
|
||||
|
||||
#include "SvgDocument.h"
|
||||
|
||||
std::string SvgWriter::toString(SvgDocument* document)
|
||||
{
|
||||
std::string content = "";
|
||||
if (auto root = document->getRoot())
|
||||
{
|
||||
content += root->toString();
|
||||
}
|
||||
return content;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class SvgDocument;
|
||||
|
||||
class SvgWriter
|
||||
{
|
||||
public:
|
||||
std::string toString(SvgDocument* document);
|
||||
};
|
62
src/web/svg/elements/SvgShapeElements.cpp
Normal file
62
src/web/svg/elements/SvgShapeElements.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "SvgShapeElements.h"
|
||||
|
||||
SvgCircle::SvgCircle()
|
||||
: SvgShapeElement("circle")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgCircle::setLocation(const DiscretePoint& loc)
|
||||
{
|
||||
auto cx = std::make_unique<XmlAttribute>("cx");
|
||||
auto cy = std::make_unique<XmlAttribute>("cy");
|
||||
|
||||
cx->setValue(std::to_string(loc.GetX()));
|
||||
cy->setValue(std::to_string(loc.GetY()));
|
||||
|
||||
addAttribute(std::move(cx));
|
||||
addAttribute(std::move(cy));
|
||||
}
|
||||
|
||||
void SvgCircle::setRadius(unsigned rad)
|
||||
{
|
||||
auto r = std::make_unique<XmlAttribute>("r");
|
||||
r->setValue(std::to_string(rad));
|
||||
addAttribute(std::move(r));
|
||||
}
|
||||
|
||||
SvgRectangle::SvgRectangle()
|
||||
: SvgShapeElement("rect")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgRectangle::setLocation(const DiscretePoint& loc)
|
||||
{
|
||||
auto x = std::make_unique<XmlAttribute>("x");
|
||||
auto y = std::make_unique<XmlAttribute>("y");
|
||||
|
||||
x->setValue(std::to_string(loc.GetX()));
|
||||
y->setValue(std::to_string(loc.GetY()));
|
||||
|
||||
addAttribute(std::move(x));
|
||||
addAttribute(std::move(y));
|
||||
}
|
||||
|
||||
void SvgRectangle::setWidth(unsigned w)
|
||||
{
|
||||
auto width = std::make_unique<XmlAttribute>("width");
|
||||
|
||||
width->setValue(std::to_string(w));
|
||||
|
||||
addAttribute(std::move(width));
|
||||
}
|
||||
|
||||
void SvgRectangle::setHeight(unsigned h)
|
||||
{
|
||||
auto height = std::make_unique<XmlAttribute>("height");
|
||||
|
||||
height->setValue(std::to_string(h));
|
||||
|
||||
addAttribute(std::move(height));
|
||||
}
|
28
src/web/svg/elements/SvgShapeElements.h
Normal file
28
src/web/svg/elements/SvgShapeElements.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "SvgShapeElement.h"
|
||||
#include "DiscretePoint.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
class SvgCircle : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
SvgCircle();
|
||||
|
||||
void setLocation(const DiscretePoint& loc);
|
||||
|
||||
void setRadius(unsigned rad);
|
||||
};
|
||||
|
||||
class SvgRectangle : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
SvgRectangle();
|
||||
|
||||
void setLocation(const DiscretePoint& loc);
|
||||
|
||||
void setWidth(unsigned width);
|
||||
|
||||
void setHeight(unsigned height);
|
||||
};
|
|
@ -9,9 +9,8 @@ std::string XmlWriter::toString(XmlDocument* document)
|
|||
if (auto prolog = document->getProlog())
|
||||
{
|
||||
content += "<?xml";
|
||||
for (std::size_t idx=0; idx< prolog->getNumAttributes(); idx++)
|
||||
for (const auto& [key, attribute] : prolog->getAttributes())
|
||||
{
|
||||
auto attribute = prolog->getAttribute(idx);
|
||||
content += " " + attribute->getName() + "=\"" + attribute->getValue() + "\"";
|
||||
}
|
||||
content += "?>\n";
|
||||
|
|
|
@ -31,7 +31,7 @@ void XmlElement::addChild(XmlElementPtr child)
|
|||
|
||||
void XmlElement::addAttribute(XmlAttributePtr attribute)
|
||||
{
|
||||
mAttributes.push_back(std::move(attribute));
|
||||
mAttributes[attribute->getName()] = std::move(attribute);
|
||||
}
|
||||
|
||||
const std::string& XmlElement::getTagName() const
|
||||
|
@ -64,28 +64,16 @@ XmlElement* XmlElement::getFirstChildWithTagName(const std::string& tag)
|
|||
|
||||
XmlAttribute* XmlElement::getAttribute(const std::string& attributeName) const
|
||||
{
|
||||
for(const auto& attribute : mAttributes)
|
||||
if (auto iter = mAttributes.find(attributeName); iter != mAttributes.end())
|
||||
{
|
||||
if(attribute->getName() == attributeName)
|
||||
{
|
||||
return attribute.get();
|
||||
}
|
||||
return iter->second.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XmlAttribute* XmlElement::getAttribute(std::size_t index) const
|
||||
const std::unordered_map<std::string, XmlAttributePtr>& XmlElement::getAttributes() const
|
||||
{
|
||||
if(index < mAttributes.size())
|
||||
{
|
||||
return mAttributes[index].get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::size_t XmlElement::getNumAttributes() const
|
||||
{
|
||||
return mAttributes.size();
|
||||
return mAttributes;
|
||||
}
|
||||
|
||||
std::size_t XmlElement::getNumChildren() const
|
||||
|
@ -105,9 +93,8 @@ std::string XmlElement::toString(unsigned depth, bool keepInline) const
|
|||
std::string line_ending = keepInline ? "" : "\n";
|
||||
|
||||
auto content = prefix + "<" + getTagName();
|
||||
for (std::size_t idx=0; idx< getNumAttributes(); idx++)
|
||||
for (const auto& [key, attribute] : getAttributes())
|
||||
{
|
||||
auto attribute = getAttribute(idx);
|
||||
content += " " + attribute->getName() + "=\"" + attribute->getValue() + "\"";
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class XmlAttribute;
|
||||
using XmlAttributePtr = std::unique_ptr<XmlAttribute>;
|
||||
|
@ -23,8 +22,7 @@ public:
|
|||
const std::string& getTagName() const;
|
||||
const std::string& getText() const;
|
||||
XmlAttribute* getAttribute(const std::string& attribute) const;
|
||||
XmlAttribute* getAttribute(std::size_t index) const;
|
||||
std::size_t getNumAttributes() const;
|
||||
const std::unordered_map<std::string, XmlAttributePtr>& getAttributes() const;
|
||||
|
||||
std::size_t getNumChildren() const;
|
||||
XmlElement* getChild(std::size_t index) const;
|
||||
|
@ -40,7 +38,7 @@ protected:
|
|||
std::string mTagName;
|
||||
std::string mText;
|
||||
|
||||
std::vector<XmlAttributePtr> mAttributes;
|
||||
std::unordered_map<std::string, XmlAttributePtr> mAttributes;
|
||||
std::vector<std::unique_ptr<XmlElement> > mChildren;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
set(WEB_UNIT_TEST_FILES
|
||||
web/TestMarkdownParser.cpp
|
||||
web/TestXmlParser.cpp
|
||||
web/TestSvgWriter.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
|
33
test/web/TestSvgWriter.cpp
Normal file
33
test/web/TestSvgWriter.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "SvgWriter.h"
|
||||
#include "SvgDocument.h"
|
||||
#include "SvgShapeElements.h"
|
||||
|
||||
#include "File.h"
|
||||
|
||||
#include "TestFramework.h"
|
||||
#include "TestUtils.h"
|
||||
|
||||
TEST_CASE(TestSvgWriter, "web")
|
||||
{
|
||||
auto document = std::make_unique<SvgDocument>();
|
||||
document->setViewBox(0, 0, 100, 100);
|
||||
|
||||
auto circle = std::make_unique<SvgCircle>();
|
||||
circle->setRadius(20);
|
||||
circle->setLocation({10, 30});
|
||||
circle->setFill({255, 0, 0});
|
||||
document->getRoot()->addChild(std::move(circle));
|
||||
|
||||
auto rectangle = std::make_unique<SvgRectangle>();
|
||||
rectangle->setLocation({50, 70});
|
||||
rectangle->setWidth(5);
|
||||
rectangle->setHeight(10);
|
||||
rectangle->setFill({0, 0, 255});
|
||||
document->getRoot()->addChild(std::move(rectangle));
|
||||
|
||||
SvgWriter writer;
|
||||
auto content = writer.toString(document.get());
|
||||
|
||||
auto outFile = std::make_unique<File>(TestUtils::getTestOutputDir(__FILE__) / "test_out.svg");
|
||||
outFile->writeText(content);
|
||||
}
|
Loading…
Reference in a new issue