Add svg conversion.

This commit is contained in:
jmsgrogan 2023-01-17 17:41:27 +00:00
parent 1f85954e98
commit dfbc87cb09
33 changed files with 602 additions and 79 deletions

View file

@ -10,12 +10,13 @@ list(APPEND publishing_HEADERS
pdf/PdfXRefTable.h
pdf/PdfWriter.h
plotting/GraphPlotter.h
plotting/SvgConverter.h
plotting/PlotNode.h
plotting/EquationNode.h
latex/LatexDocument.h
latex/LatexMathExpression.h
latex/LatexSymbols.h
svg/SvgNode.h
svg/SvgPainter.h
DocumentConverter.h
)
@ -34,10 +35,11 @@ list(APPEND publishing_LIB_INCLUDES
latex/LatexMathExpression.cpp
latex/LatexSymbols.cpp
plotting/GraphPlotter.h
plotting/SvgConverter.cpp
plotting/PlotNode.cpp
plotting/EquationNode.cpp
DocumentConverter.cpp
svg/SvgNode.cpp
svg/SvgPainter.cpp
)
add_library(publishing SHARED ${publishing_LIB_INCLUDES} ${publishing_INCLUDES} ${publishing_HEADERS})
@ -47,6 +49,7 @@ target_include_directories(publishing PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/pdf
${CMAKE_CURRENT_SOURCE_DIR}/plotting
${CMAKE_CURRENT_SOURCE_DIR}/latex
${CMAKE_CURRENT_SOURCE_DIR}/svg
)
set_target_properties( publishing PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
target_link_libraries( publishing PUBLIC core web graphics visual_elements)

View file

@ -1,30 +0,0 @@
#pragma once
#include <memory>
class SvgDocument;
class SvgShapeElement;
class XmlAttribute;
class Scene;
class SceneModel;
class SceneText;
class Transform;
class SvgConverter
{
public:
std::unique_ptr<SvgDocument> convert(Scene* scene, double width = 800.0, double height = 800.0) const;
private:
void convertMesh(SvgDocument* document, SceneModel* model, bool showOutline = false) const;
void convertPrimitive(SvgDocument* document, SceneModel* model) const;
void convertText(SvgDocument* document, SceneText* model) const;
void setStyle(SceneModel* model, SvgShapeElement* element) const;
std::unique_ptr<XmlAttribute> toTransform(const Transform& transform) const;
};

View file

@ -0,0 +1,90 @@
#include "SvgNode.h"
#include "CircleNode.h"
#include "SvgShapeElements.h"
SvgNode::SvgNode(const Point& location)
: AbstractVisualNode(location)
{
}
void SvgNode::setContent(std::unique_ptr<SvgDocument> doc)
{
mContent = std::move(doc);
mContentDirty = true;
mChildren.clear();
mManagedChildren.clear();
}
void SvgNode::updateTransform()
{
}
void SvgNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (!mContent->getRoot())
{
return;
}
auto viewbox = mContent->getViewBox();
for (const auto& svg_element : mContent->getRoot()->getChildren())
{
std::unique_ptr<AbstractVisualNode> node;
if (svg_element->getTagName() == "circle")
{
auto svg_circle = dynamic_cast<SvgCircle*>(svg_element.get());
auto loc = svg_circle->getLocation();
auto radius = svg_circle->getRadius();
auto minor_radius = radius;
if (svg_circle->getType() == SvgCircle::Type::ELLIPSE)
{
minor_radius = svg_circle->getMinorRadius();
}
if (svg_element->hasAttribute("transform"))
{
const auto transform = svg_circle->getTransform();
loc.move(transform.getLocation().getX(), transform.getLocation().getY());
radius *= transform.getScaleX();
minor_radius *= transform.getScaleY();
}
auto circle_node = std::make_unique<CircleNode>(loc, radius);
circle_node->setMinorRadius(minor_radius);
node = std::move(circle_node);
}
if (!node)
{
continue;
}
auto raw_node = node.get();
mManagedChildren.push_back(std::move(node));
addChild(raw_node);
}
}
void SvgNode::update(SceneInfo* sceneInfo)
{
if (mContent && mContentDirty)
{
createOrUpdateGeometry(sceneInfo);
mContentDirty = false;
}
if (mTransformIsDirty)
{
updateTransform();
mTransformIsDirty = false;
}
}

View file

@ -0,0 +1,25 @@
#pragma once
#include "AbstractVisualNode.h"
#include "SvgDocument.h"
#include <memory>
#include <vector>
class SvgNode : public AbstractVisualNode
{
public:
SvgNode(const Point& location);
void setContent(std::unique_ptr<SvgDocument> doc);
void update(SceneInfo* sceneInfo);
private:
void createOrUpdateGeometry(SceneInfo* sceneInfo);
void updateTransform();
bool mContentDirty{ true };
std::vector<std::unique_ptr<AbstractVisualNode> > mManagedChildren;
std::unique_ptr<SvgDocument> mContent;
};

View file

@ -1,4 +1,4 @@
#include "SvgConverter.h"
#include "SvgPainter.h"
#include "SvgDocument.h"
#include "Scene.h"
@ -17,38 +17,38 @@
#include "SvgShapeElements.h"
#include "XmlAttribute.h"
std::unique_ptr<SvgDocument> SvgConverter::convert(Scene* scene, double width, double height) const
std::unique_ptr<SvgDocument> SvgPainter::paint(Scene* scene, double width, double height) const
{
auto doc = std::make_unique<SvgDocument>();
doc->setViewBox(0.0, 0.0, width, height);
scene->update();
for(auto item : scene->getItems())
for (auto item : scene->getItems())
{
if (item->getType() == SceneItem::Type::MODEL)
{
auto model = dynamic_cast<SceneModel*>(item);
if (model->getGeometry())
{
convertPrimitive(doc.get(), model);
paintPrimitive(doc.get(), model);
}
else
{
convertMesh(doc.get(), model, scene->shouldShowMeshOutline());
paintMesh(doc.get(), model, scene->shouldShowMeshOutline());
}
}
else
{
auto text = dynamic_cast<SceneText*>(item);
convertText(doc.get(), text);
paintText(doc.get(), text);
}
}
return std::move(doc);
}
void SvgConverter::convertMesh(SvgDocument* document, SceneModel* model, bool showOutline) const
void SvgPainter::paintMesh(SvgDocument* document, SceneModel* model, bool showOutline) const
{
auto mesh = model->getMesh();
auto transform = model->getTransform();
@ -87,7 +87,7 @@ void SvgConverter::convertMesh(SvgDocument* document, SceneModel* model, bool sh
}
}
void SvgConverter::setStyle(SceneModel* model, SvgShapeElement* element) const
void SvgPainter::setStyle(SceneModel* model, SvgShapeElement* element) const
{
auto transform = model->getTransform();
@ -111,7 +111,7 @@ void SvgConverter::setStyle(SceneModel* model, SvgShapeElement* element) const
element->addAttribute(std::move(toTransform(transform)));
}
void SvgConverter::convertPrimitive(SvgDocument* document, SceneModel* model) const
void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const
{
if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE)
{
@ -139,12 +139,12 @@ void SvgConverter::convertPrimitive(SvgDocument* document, SceneModel* model) co
}
}
void SvgConverter::convertText(SvgDocument* document, SceneText* model) const
void SvgPainter::paintText(SvgDocument* document, SceneText* model) const
{
}
std::unique_ptr<XmlAttribute> SvgConverter::toTransform(const Transform& transform) const
std::unique_ptr<XmlAttribute> SvgPainter::toTransform(const Transform& transform) const
{
auto svg_transform = std::make_unique<XmlAttribute>("transform");

View file

@ -0,0 +1,32 @@
#pragma once
#include "AbstractPainter.h"
#include <memory>
class SvgDocument;
class SvgShapeElement;
class XmlAttribute;
class Scene;
class SceneModel;
class SceneText;
class Transform;
class SvgPainter
{
public:
std::unique_ptr<SvgDocument> paint(Scene* scene, double width = 800.0, double height = 800.0) const;
private:
void paintMesh(SvgDocument* document, SceneModel* model, bool showOutline = false) const;
void paintPrimitive(SvgDocument* document, SceneModel* model) const;
void paintText(SvgDocument* document, SceneText* model) const;
void setStyle(SceneModel* model, SvgShapeElement* element) const;
std::unique_ptr<XmlAttribute> toTransform(const Transform& transform) const;
};