Add path rendering and svg line output.
This commit is contained in:
parent
73051a5f27
commit
6274c41a80
15 changed files with 281 additions and 79 deletions
|
@ -3,78 +3,105 @@
|
||||||
#include "PointParser.h"
|
#include "PointParser.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
Arc::Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation, bool largeArc, bool sweep)
|
namespace ntk {
|
||||||
: mStartPoint(startPoint),
|
Arc::Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation, bool largeArc, bool sweep)
|
||||||
mEndPoint(endPoint),
|
: mStartPoint(startPoint),
|
||||||
mRx(rX),
|
mEndPoint(endPoint),
|
||||||
mRy(rY),
|
mRx(rX),
|
||||||
mRotation(rotation),
|
mRy(rY),
|
||||||
mLargeArc(largeArc),
|
mRotation(rotation),
|
||||||
mSweep(sweep)
|
mLargeArc(largeArc),
|
||||||
{
|
mSweep(sweep)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Arc::getFirstPoint() const
|
|
||||||
{
|
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Arc::getEndPoint() const
|
|
||||||
{
|
|
||||||
return mEndPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Arc::toPostScriptString(std::size_t precision) const
|
|
||||||
{
|
|
||||||
const auto large = mLargeArc ? "1" : "0";
|
|
||||||
const auto sweep = mSweep ? "1" : "0";
|
|
||||||
std::stringstream sstr;
|
|
||||||
if (precision > 0)
|
|
||||||
{
|
{
|
||||||
sstr.precision(precision);
|
|
||||||
}
|
}
|
||||||
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
|
||||||
|
Point Arc::getFirstPoint() const
|
||||||
{
|
{
|
||||||
sstr << "a";
|
return mStartPoint;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
Point Arc::getEndPoint() const
|
||||||
{
|
{
|
||||||
sstr << "A";
|
return mEndPoint;
|
||||||
}
|
}
|
||||||
sstr << mRx << " " << mRy << " " << mRotation << " " << large << " " << sweep << " ";
|
|
||||||
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
std::string Arc::toPostScriptString(std::size_t precision) const
|
||||||
{
|
{
|
||||||
sstr << PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision);
|
const auto large = mLargeArc ? "1" : "0";
|
||||||
|
const auto sweep = mSweep ? "1" : "0";
|
||||||
|
std::stringstream sstr;
|
||||||
|
if (precision > 0)
|
||||||
|
{
|
||||||
|
sstr.precision(precision);
|
||||||
|
}
|
||||||
|
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
||||||
|
{
|
||||||
|
sstr << "a";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sstr << "A";
|
||||||
|
}
|
||||||
|
sstr << mRx << " " << mRy << " " << mRotation << " " << large << " " << sweep << " ";
|
||||||
|
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
||||||
|
{
|
||||||
|
sstr << PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sstr << PointParser::toString(mEndPoint, 2, " ", precision);
|
||||||
|
}
|
||||||
|
return sstr.str();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
Bounds Arc::getBounds() const
|
||||||
{
|
{
|
||||||
sstr << PointParser::toString(mEndPoint, 2, " ", precision);
|
return {};
|
||||||
}
|
}
|
||||||
return sstr.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
Bounds Arc::getBounds() const
|
const Point& Arc::getLocation() const
|
||||||
{
|
{
|
||||||
return {};
|
return mStartPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Arc::getLocation() const
|
void Arc::sample(SparseGrid<bool>*) const
|
||||||
{
|
{
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Arc::sample(SparseGrid<bool>*) const
|
}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
Arc::Type Arc::getType() const
|
||||||
|
{
|
||||||
|
return Type::CURVE;
|
||||||
|
}
|
||||||
|
|
||||||
Arc::Type Arc::getType() const
|
Arc::CurveType Arc::getCurveType() const
|
||||||
{
|
{
|
||||||
return Type::CURVE;
|
return CurveType::ARC;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arc::CurveType Arc::getCurveType() const
|
double Arc::getRx() const
|
||||||
{
|
{
|
||||||
return CurveType::ARC;
|
return mRx;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Arc::getRy() const
|
||||||
|
{
|
||||||
|
return mRy;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Arc::getRotation() const
|
||||||
|
{
|
||||||
|
return mRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Arc::getUseLargeArc() const
|
||||||
|
{
|
||||||
|
return mLargeArc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Arc::getSweepParam() const
|
||||||
|
{
|
||||||
|
return mSweep;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
|
|
||||||
|
namespace ntk{
|
||||||
class Arc : public Curve
|
class Arc : public Curve
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -20,6 +21,16 @@ public:
|
||||||
|
|
||||||
CurveType getCurveType() const override;
|
CurveType getCurveType() const override;
|
||||||
|
|
||||||
|
double getRx() const;
|
||||||
|
|
||||||
|
double getRy() const;
|
||||||
|
|
||||||
|
double getRotation() const;
|
||||||
|
|
||||||
|
bool getUseLargeArc() const;
|
||||||
|
|
||||||
|
bool getSweepParam() const;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
void sample(SparseGrid<bool>*) const override;
|
||||||
|
|
||||||
std::string toPostScriptString(std::size_t precision = 0) const override;
|
std::string toPostScriptString(std::size_t precision = 0) const override;
|
||||||
|
@ -33,3 +44,4 @@ private:
|
||||||
bool mLargeArc{ false };
|
bool mLargeArc{ false };
|
||||||
bool mSweep{ false };
|
bool mSweep{ false };
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,16 @@ Point CubicBezierCurve::getEndPoint() const
|
||||||
return mEndPoint;
|
return mEndPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Point& CubicBezierCurve::getStartControlPoint() const
|
||||||
|
{
|
||||||
|
return mStartControlPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Point& CubicBezierCurve::getEndControlPoint() const
|
||||||
|
{
|
||||||
|
return mEndControlPoint;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CubicBezierCurve::toPostScriptString(std::size_t precision) const
|
std::string CubicBezierCurve::toPostScriptString(std::size_t precision) const
|
||||||
{
|
{
|
||||||
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
||||||
|
|
|
@ -12,6 +12,10 @@ public:
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
Point getEndPoint() const override;
|
||||||
|
|
||||||
|
const Point& getStartControlPoint() const;
|
||||||
|
|
||||||
|
const Point& getEndControlPoint() const;
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
const Point& getLocation() const override;
|
||||||
|
|
|
@ -249,12 +249,12 @@ PathElementPtr PathPostScriptConverter::onArc()
|
||||||
if (mPositionState == PositionState::RELATIVE)
|
if (mPositionState == PositionState::RELATIVE)
|
||||||
{
|
{
|
||||||
const auto end_point = Point(mCurrentPoint.getX() + mPointBuffer[5], mCurrentPoint.getY() + mPointBuffer[6]);
|
const auto end_point = Point(mCurrentPoint.getX() + mPointBuffer[5], mCurrentPoint.getY() + mPointBuffer[6]);
|
||||||
element = std::make_unique<Arc>(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep);
|
element = std::make_unique<ntk::Arc>(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto end_point = Point(mPointBuffer[5], mPointBuffer[6]);
|
const auto end_point = Point(mPointBuffer[5], mPointBuffer[6]);
|
||||||
element = std::make_unique<Arc>(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep);
|
element = std::make_unique<ntk::Arc>(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
|
|
|
@ -20,6 +20,11 @@ Point QuadraticBezierCurve::getEndPoint() const
|
||||||
return mEndPoint;
|
return mEndPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point QuadraticBezierCurve::getControlPoint() const
|
||||||
|
{
|
||||||
|
return mControlPoint;
|
||||||
|
}
|
||||||
|
|
||||||
std::string QuadraticBezierCurve::toPostScriptString(std::size_t precision) const
|
std::string QuadraticBezierCurve::toPostScriptString(std::size_t precision) const
|
||||||
{
|
{
|
||||||
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
|
||||||
|
|
|
@ -10,6 +10,8 @@ public:
|
||||||
|
|
||||||
Point getFirstPoint() const override;
|
Point getFirstPoint() const override;
|
||||||
|
|
||||||
|
Point getControlPoint() const;
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
Point getEndPoint() const override;
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
|
@ -195,7 +195,6 @@ void DirectX2dPainter::paintPath(SceneModel* model)
|
||||||
for (const auto& feature : path_item->getFeatures())
|
for (const auto& feature : path_item->getFeatures())
|
||||||
{
|
{
|
||||||
const auto loc = feature->getLocation();
|
const auto loc = feature->getLocation();
|
||||||
MLOG_INFO("Starting feature at: " << loc.getX() << " " << loc.getY());
|
|
||||||
path_sink->BeginFigure(toD2dPoint(loc), D2D1_FIGURE_BEGIN_FILLED);
|
path_sink->BeginFigure(toD2dPoint(loc), D2D1_FIGURE_BEGIN_FILLED);
|
||||||
|
|
||||||
for (const auto& element : feature->getElements())
|
for (const auto& element : feature->getElements())
|
||||||
|
@ -246,39 +245,48 @@ void DirectX2dPainter::paintPath(SceneModel* model)
|
||||||
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
|
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
|
||||||
rt->DrawGeometry(path_geom.Get(), mSolidBrush.Get(), 1.0f);
|
rt->DrawGeometry(path_geom.Get(), mSolidBrush.Get(), 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onArc(Curve* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onArc(Curve* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
|
auto arc = dynamic_cast<ntk::Arc*>(element);
|
||||||
|
|
||||||
|
const auto end = toD2dPoint(arc->getEndPoint());
|
||||||
|
D2D1_SIZE_F size{static_cast<float>(arc->getRx()), static_cast<float>(arc->getRx()) };
|
||||||
|
const auto angle = static_cast<float>(arc->getRotation());
|
||||||
|
D2D1_SWEEP_DIRECTION direction = arc->getSweepParam() ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE;
|
||||||
|
D2D1_ARC_SIZE arc_size = arc->getUseLargeArc() ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL;
|
||||||
|
|
||||||
|
D2D1_ARC_SEGMENT segment{ end , size , angle , direction , arc_size };
|
||||||
|
sink->AddArc(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onQuadraticBezier(Curve* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onQuadraticBezier(Curve* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
|
auto bezier = dynamic_cast<QuadraticBezierCurve*>(element);
|
||||||
|
D2D1_QUADRATIC_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getControlPoint()) , toD2dPoint(bezier->getEndPoint()) };
|
||||||
|
sink->AddQuadraticBezier(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onCubicBezier(Curve* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onCubicBezier(Curve* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
|
auto bezier = dynamic_cast<CubicBezierCurve*>(element);
|
||||||
|
D2D1_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getStartControlPoint()), toD2dPoint(bezier->getEndControlPoint()), toD2dPoint(bezier->getEndPoint()) };
|
||||||
|
sink->AddBezier(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onLine(PathElement* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onLine(PathElement* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
for (const auto& point : dynamic_cast<Line*>(element)->getPoints().getPoints())
|
for (const auto& point : dynamic_cast<Line*>(element)->getPoints().getPoints())
|
||||||
{
|
{
|
||||||
MLOG_INFO("Adding line entry at: " << point.getX() << " " << point.getY());
|
|
||||||
sink->AddLine(toD2dPoint(point));
|
sink->AddLine(toD2dPoint(point));
|
||||||
}
|
}
|
||||||
MLOG_INFO("Finished line");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onLineSegment(PathElement* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onLineSegment(PathElement* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
const auto loc = element->getEndPoint();
|
const auto loc = element->getEndPoint();
|
||||||
MLOG_INFO("Adding segment entry at: " << loc.getX() << " " << loc.getY());
|
|
||||||
sink->AddLine(toD2dPoint(loc));
|
sink->AddLine(toD2dPoint(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include "Circle.h"
|
#include "Circle.h"
|
||||||
#include "Rectangle.h"
|
#include "Rectangle.h"
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
|
#include "Line.h"
|
||||||
|
#include "LineSegment.h"
|
||||||
|
|
||||||
#include "SvgShapeElements.h"
|
#include "SvgShapeElements.h"
|
||||||
#include "SvgTextElement.h"
|
#include "SvgTextElement.h"
|
||||||
|
@ -139,6 +141,14 @@ void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
paintPath(document, model);
|
paintPath(document, model);
|
||||||
}
|
}
|
||||||
|
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::LINE)
|
||||||
|
{
|
||||||
|
paintLine(document, model);
|
||||||
|
}
|
||||||
|
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::LINE_SEGMENT)
|
||||||
|
{
|
||||||
|
paintLineSegment(document, model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgPainter::paintRect(SvgDocument* document, SceneModel* model) const
|
void SvgPainter::paintRect(SvgDocument* document, SceneModel* model) const
|
||||||
|
@ -173,6 +183,25 @@ void SvgPainter::paintCircle(SvgDocument* document, SceneModel* model) const
|
||||||
document->getRoot()->addChild(std::move(circle));
|
document->getRoot()->addChild(std::move(circle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SvgPainter::paintLine(SvgDocument* document, SceneModel* model) const
|
||||||
|
{
|
||||||
|
auto model_line = dynamic_cast<Line*>(model->getGeometry());
|
||||||
|
auto svg_line = std::make_unique<SvgPolyline>();
|
||||||
|
svg_line->setPoints(model_line->getFirstPoint(), model_line->getPoints().getPoints());
|
||||||
|
|
||||||
|
setStyle(model, svg_line.get());
|
||||||
|
document->getRoot()->addChild(std::move(svg_line));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgPainter::paintLineSegment(SvgDocument* document, SceneModel* model) const
|
||||||
|
{
|
||||||
|
auto model_line = dynamic_cast<LineSegment*>(model->getGeometry());
|
||||||
|
auto svg_line = std::make_unique<SvgLine>(model_line->getFirstPoint(), model_line->getEndPoint());
|
||||||
|
|
||||||
|
setStyle(model, svg_line.get());
|
||||||
|
document->getRoot()->addChild(std::move(svg_line));
|
||||||
|
}
|
||||||
|
|
||||||
void SvgPainter::paintPath(SvgDocument* document, SceneModel* model) const
|
void SvgPainter::paintPath(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
auto model_path = dynamic_cast<GeometryPath*>(model->getGeometry());
|
auto model_path = dynamic_cast<GeometryPath*>(model->getGeometry());
|
||||||
|
|
|
@ -26,6 +26,10 @@ private:
|
||||||
|
|
||||||
void paintCircle(SvgDocument* document, SceneModel* model) const;
|
void paintCircle(SvgDocument* document, SceneModel* model) const;
|
||||||
|
|
||||||
|
void paintLine(SvgDocument* document, SceneModel* model) const;
|
||||||
|
|
||||||
|
void paintLineSegment(SvgDocument* document, SceneModel* model) const;
|
||||||
|
|
||||||
void paintPath(SvgDocument* document, SceneModel* model) const;
|
void paintPath(SvgDocument* document, SceneModel* model) const;
|
||||||
|
|
||||||
void paintText(SvgDocument* document, SceneText* model) const;
|
void paintText(SvgDocument* document, SceneText* model) const;
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
SvgShapeElement::SvgShapeElement(const std::string& tagName)
|
SvgShapeElement::SvgShapeElement(const std::string& tagName, std::size_t precision)
|
||||||
: SvgElement(tagName)
|
: SvgElement(tagName),
|
||||||
|
mPrecision(precision)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
class SvgShapeElement : public SvgElement
|
class SvgShapeElement : public SvgElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SvgShapeElement(const std::string& tagName);
|
SvgShapeElement(const std::string& tagName, std::size_t precision = 0);
|
||||||
|
|
||||||
Transform getTransform() const;
|
Transform getTransform() const;
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@ public:
|
||||||
|
|
||||||
void setNoStroke();
|
void setNoStroke();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::size_t mPrecision{ 0 };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getLabelledContent(const std::string& key, const std::string& content) const;
|
std::string getLabelledContent(const std::string& key, const std::string& content) const;
|
||||||
Point parsePoint(const std::string& pointString, double defaultVal = 0.0) const;
|
Point parsePoint(const std::string& pointString, double defaultVal = 0.0) const;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "SvgShapeElements.h"
|
#include "SvgShapeElements.h"
|
||||||
|
|
||||||
|
#include "PointParser.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
SvgCircle::SvgCircle(Type type)
|
SvgCircle::SvgCircle(Type type)
|
||||||
|
@ -174,6 +175,45 @@ void SvgPolyline::setPoints(const std::vector<Point>& locs)
|
||||||
addAttribute(std::move(points));
|
addAttribute(std::move(points));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SvgPolyline::setPoints(const Point& startPoint, const std::vector<Point>& locs)
|
||||||
|
{
|
||||||
|
auto points = std::make_unique<XmlAttribute>("points");
|
||||||
|
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << startPoint.getX() << "," << startPoint.getY() << " ";
|
||||||
|
|
||||||
|
for (const auto& loc : locs)
|
||||||
|
{
|
||||||
|
sstr << loc.getX() << "," << loc.getY() << " ";
|
||||||
|
}
|
||||||
|
points->setValue(sstr.str());
|
||||||
|
addAttribute(std::move(points));
|
||||||
|
}
|
||||||
|
|
||||||
|
SvgLine::SvgLine(const Point& startPoint, const Point& endPoint, std::size_t precision)
|
||||||
|
: SvgShapeElement("line", precision)
|
||||||
|
{
|
||||||
|
auto fill = std::make_unique<XmlAttribute>("fill");
|
||||||
|
fill->setValue("none");
|
||||||
|
addAttribute(std::move(fill));
|
||||||
|
|
||||||
|
auto x1 = std::make_unique<XmlAttribute>("x1");
|
||||||
|
x1->setValue(PointParser::toString(startPoint.getX(), mPrecision));
|
||||||
|
addAttribute(std::move(x1));
|
||||||
|
|
||||||
|
auto y1 = std::make_unique<XmlAttribute>("y1");
|
||||||
|
y1->setValue(PointParser::toString(startPoint.getY(), mPrecision));
|
||||||
|
addAttribute(std::move(y1));
|
||||||
|
|
||||||
|
auto x2 = std::make_unique<XmlAttribute>("x2");
|
||||||
|
x2->setValue(PointParser::toString(endPoint.getX(), mPrecision));
|
||||||
|
addAttribute(std::move(x2));
|
||||||
|
|
||||||
|
auto y2 = std::make_unique<XmlAttribute>("y2");
|
||||||
|
y2->setValue(PointParser::toString(endPoint.getY(), mPrecision));
|
||||||
|
addAttribute(std::move(y2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SvgPath::SvgPath()
|
SvgPath::SvgPath()
|
||||||
: SvgShapeElement("path")
|
: SvgShapeElement("path")
|
||||||
|
|
|
@ -60,9 +60,17 @@ class SvgPolyline : public SvgShapeElement
|
||||||
public:
|
public:
|
||||||
SvgPolyline();
|
SvgPolyline();
|
||||||
|
|
||||||
|
void setPoints(const Point& startPoint, const std::vector<Point>& loc);
|
||||||
|
|
||||||
void setPoints(const std::vector<Point>& loc);
|
void setPoints(const std::vector<Point>& loc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SvgLine : public SvgShapeElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SvgLine(const Point& startPoint, const Point& endPoint, std::size_t precision = 0);
|
||||||
|
};
|
||||||
|
|
||||||
class SvgPath : public SvgShapeElement
|
class SvgPath : public SvgShapeElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
#include "LineNode.h"
|
#include "LineNode.h"
|
||||||
#include "PathNode.h"
|
#include "PathNode.h"
|
||||||
|
|
||||||
void addRect(const Point& loc, std::vector<std::unique_ptr<AbstractVisualNode> >& nodes, double radius = 0.0)
|
void addRect(const Point& loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, double radius = 0.0)
|
||||||
{
|
{
|
||||||
auto node = std::make_unique<RectangleNode>(loc, 150.0, 100.0);
|
auto node = std::make_unique<RectangleNode>(loc, 150.0, 100.0);
|
||||||
node->setRadius(radius);
|
node->setRadius(radius);
|
||||||
nodes.push_back(std::move(node));
|
nodes.push_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCircle(const Point& loc, std::vector<std::unique_ptr<AbstractVisualNode> >& nodes, double minorRadius = 0.0)
|
void addCircle(const Point& loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, double minorRadius = 0.0)
|
||||||
{
|
{
|
||||||
const auto radius = 50.0;
|
const auto radius = 50.0;
|
||||||
auto centre_loc = loc;
|
auto centre_loc = loc;
|
||||||
|
@ -30,26 +30,25 @@ void addCircle(const Point& loc, std::vector<std::unique_ptr<AbstractVisualNode>
|
||||||
nodes.push_back(std::move(node));
|
nodes.push_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLine(const Point& loc, std::vector<std::unique_ptr<AbstractVisualNode> >& nodes)
|
void addLine(const Point& loc, std::vector<std::unique_ptr<MaterialNode> >& nodes)
|
||||||
{
|
{
|
||||||
std::vector<Point> points = { Point(150.0, 100.0) };
|
std::vector<Point> points = { Point(150.0, 100.0) };
|
||||||
auto node = std::make_unique<LineNode>(loc, points);
|
auto node = std::make_unique<LineNode>(loc, points);
|
||||||
nodes.push_back(std::move(node));
|
nodes.push_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPath(const Point& loc, const std::string& path, std::vector<std::unique_ptr<AbstractVisualNode> >& nodes)
|
void addPath(const Point& loc, const std::string& path, std::vector<std::unique_ptr<MaterialNode> >& nodes)
|
||||||
{
|
{
|
||||||
auto node = std::make_unique<PathNode>(loc, path);
|
auto node = std::make_unique<PathNode>(loc, path);
|
||||||
nodes.push_back(std::move(node));
|
nodes.push_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(TestD2dOffScreenRendering, "graphics")
|
void addShapes(const Point& start_loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, bool use_fill = false)
|
||||||
{
|
{
|
||||||
TestRenderer renderer(800, 800);
|
auto loc = start_loc;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<AbstractVisualNode> > nodes;
|
auto fill_color = Color(200, 0, 200);
|
||||||
|
|
||||||
auto loc = Point(10, 10);
|
|
||||||
addRect(loc, nodes);
|
addRect(loc, nodes);
|
||||||
|
|
||||||
loc.move(250, 0);
|
loc.move(250, 0);
|
||||||
|
@ -67,10 +66,60 @@ TEST_CASE(TestD2dOffScreenRendering, "graphics")
|
||||||
loc.move(100, 0);
|
loc.move(100, 0);
|
||||||
addPath(loc, "M0 0 h150 v100 h-150Z", nodes);
|
addPath(loc, "M0 0 h150 v100 h-150Z", nodes);
|
||||||
|
|
||||||
|
loc = Point(10, 300);
|
||||||
|
addPath(loc, "M0 0 h150 q50 50 0 100 h-150Z", nodes);
|
||||||
|
|
||||||
|
loc.move(250, 0);
|
||||||
|
addPath(loc, "M0 0 h150 c25 25 25 75 0 100 h-150Z", nodes);
|
||||||
|
|
||||||
|
loc.move(250, 0);
|
||||||
|
addPath(loc, "M0 0 h150 a50 50 0 0 1 0 100 h-150Z", nodes);
|
||||||
|
|
||||||
|
if (use_fill)
|
||||||
|
{
|
||||||
|
for (auto& node : nodes)
|
||||||
|
{
|
||||||
|
node->setFillColor(fill_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(TestD2dOffScreenRendering_Outlines, "graphics")
|
||||||
|
{
|
||||||
|
TestRenderer renderer(800, 800);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<MaterialNode> > nodes;
|
||||||
|
|
||||||
|
auto loc = Point(10, 10);
|
||||||
|
|
||||||
|
addShapes(loc, nodes, false);
|
||||||
|
|
||||||
auto scene = renderer.getScene();
|
auto scene = renderer.getScene();
|
||||||
for (const auto& node : nodes)
|
for (const auto& node : nodes)
|
||||||
{
|
{
|
||||||
scene->addNode(node.get());
|
scene->addNode(node.get());
|
||||||
}
|
}
|
||||||
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "out.png");
|
|
||||||
|
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "outlines.svg");
|
||||||
|
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "outlines.png");
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE(TestD2dOffScreenRendering_Fill, "graphics")
|
||||||
|
{
|
||||||
|
TestRenderer renderer(800, 800);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<MaterialNode> > nodes;
|
||||||
|
|
||||||
|
auto loc = Point(10, 10);
|
||||||
|
|
||||||
|
addShapes(loc, nodes, true);
|
||||||
|
|
||||||
|
auto scene = renderer.getScene();
|
||||||
|
for (const auto& node : nodes)
|
||||||
|
{
|
||||||
|
scene->addNode(node.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "fill.svg");
|
||||||
|
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "fill.png");
|
||||||
};
|
};
|
Loading…
Reference in a new issue