mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
336 lines
7.7 KiB
C++
336 lines
7.7 KiB
C++
#include "geometryelement.h"
|
|
#include "parser.h"
|
|
#include "layoutcontext.h"
|
|
|
|
#include <cmath>
|
|
|
|
namespace lunasvg {
|
|
|
|
GeometryElement::GeometryElement(ElementID id)
|
|
: GraphicsElement(id)
|
|
{
|
|
}
|
|
|
|
void GeometryElement::layout(LayoutContext* context, LayoutContainer* current) const
|
|
{
|
|
if(isDisplayNone())
|
|
return;
|
|
|
|
auto path = this->path();
|
|
if(path.empty())
|
|
return;
|
|
|
|
auto shape = std::make_unique<LayoutShape>();
|
|
shape->path = std::move(path);
|
|
shape->transform = transform();
|
|
shape->fillData = context->fillData(this);
|
|
shape->strokeData = context->strokeData(this);
|
|
shape->markerData = context->markerData(this, shape->path);
|
|
shape->visibility = visibility();
|
|
shape->clipRule = clip_rule();
|
|
shape->opacity = opacity();
|
|
shape->masker = context->getMasker(mask());
|
|
shape->clipper = context->getClipper(clip_path());
|
|
current->addChild(std::move(shape));
|
|
}
|
|
|
|
PathElement::PathElement()
|
|
: GeometryElement(ElementID::Path)
|
|
{
|
|
}
|
|
|
|
Path PathElement::d() const
|
|
{
|
|
auto& value = get(PropertyID::D);
|
|
return Parser::parsePath(value);
|
|
}
|
|
|
|
Path PathElement::path() const
|
|
{
|
|
return d();
|
|
}
|
|
|
|
std::unique_ptr<Node> PathElement::clone() const
|
|
{
|
|
return cloneElement<PathElement>();
|
|
}
|
|
|
|
PolyElement::PolyElement(ElementID id)
|
|
: GeometryElement(id)
|
|
{
|
|
}
|
|
|
|
PointList PolyElement::points() const
|
|
{
|
|
auto& value = get(PropertyID::Points);
|
|
return Parser::parsePointList(value);
|
|
}
|
|
|
|
PolygonElement::PolygonElement()
|
|
: PolyElement(ElementID::Polygon)
|
|
{
|
|
}
|
|
|
|
Path PolygonElement::path() const
|
|
{
|
|
auto points = this->points();
|
|
if(points.empty())
|
|
return Path{};
|
|
|
|
Path path;
|
|
path.moveTo(points[0].x, points[0].y);
|
|
for(std::size_t i = 1; i < points.size(); i++)
|
|
path.lineTo(points[i].x, points[i].y);
|
|
|
|
path.close();
|
|
return path;
|
|
}
|
|
|
|
std::unique_ptr<Node> PolygonElement::clone() const
|
|
{
|
|
return cloneElement<PolygonElement>();
|
|
}
|
|
|
|
PolylineElement::PolylineElement()
|
|
: PolyElement(ElementID::Polyline)
|
|
{
|
|
}
|
|
|
|
Path PolylineElement::path() const
|
|
{
|
|
auto points = this->points();
|
|
if(points.empty())
|
|
return Path{};
|
|
|
|
Path path;
|
|
path.moveTo(points[0].x, points[0].y);
|
|
for(std::size_t i = 1; i < points.size(); i++)
|
|
path.lineTo(points[i].x, points[i].y);
|
|
|
|
return path;
|
|
}
|
|
|
|
std::unique_ptr<Node> PolylineElement::clone() const
|
|
{
|
|
return cloneElement<PolylineElement>();
|
|
}
|
|
|
|
CircleElement::CircleElement()
|
|
: GeometryElement(ElementID::Circle)
|
|
{
|
|
}
|
|
|
|
Length CircleElement::cx() const
|
|
{
|
|
auto& value = get(PropertyID::Cx);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length CircleElement::cy() const
|
|
{
|
|
auto& value = get(PropertyID::Cy);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length CircleElement::r() const
|
|
{
|
|
auto& value = get(PropertyID::R);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Path CircleElement::path() const
|
|
{
|
|
auto r = this->r();
|
|
if(r.isZero())
|
|
return Path{};
|
|
|
|
LengthContext lengthContext(this);
|
|
auto _cx = lengthContext.valueForLength(cx(), LengthMode::Width);
|
|
auto _cy = lengthContext.valueForLength(cy(), LengthMode::Height);
|
|
auto _r = lengthContext.valueForLength(r, LengthMode::Both);
|
|
|
|
Path path;
|
|
path.ellipse(_cx, _cy, _r, _r);
|
|
return path;
|
|
}
|
|
|
|
std::unique_ptr<Node> CircleElement::clone() const
|
|
{
|
|
return cloneElement<CircleElement>();
|
|
}
|
|
|
|
EllipseElement::EllipseElement()
|
|
: GeometryElement(ElementID::Ellipse)
|
|
{
|
|
}
|
|
|
|
Length EllipseElement::cx() const
|
|
{
|
|
auto& value = get(PropertyID::Cx);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length EllipseElement::cy() const
|
|
{
|
|
auto& value = get(PropertyID::Cy);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length EllipseElement::rx() const
|
|
{
|
|
auto& value = get(PropertyID::Rx);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length EllipseElement::ry() const
|
|
{
|
|
auto& value = get(PropertyID::Ry);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Path EllipseElement::path() const
|
|
{
|
|
auto rx = this->rx();
|
|
auto ry = this->ry();
|
|
if(rx.isZero() || ry.isZero())
|
|
return Path{};
|
|
|
|
LengthContext lengthContext(this);
|
|
auto _cx = lengthContext.valueForLength(cx(), LengthMode::Width);
|
|
auto _cy = lengthContext.valueForLength(cy(), LengthMode::Height);
|
|
auto _rx = lengthContext.valueForLength(rx, LengthMode::Width);
|
|
auto _ry = lengthContext.valueForLength(ry, LengthMode::Height);
|
|
|
|
Path path;
|
|
path.ellipse(_cx, _cy, _rx, _ry);
|
|
return path;
|
|
}
|
|
|
|
std::unique_ptr<Node> EllipseElement::clone() const
|
|
{
|
|
return cloneElement<EllipseElement>();
|
|
}
|
|
|
|
LineElement::LineElement()
|
|
: GeometryElement(ElementID::Line)
|
|
{
|
|
}
|
|
|
|
Length LineElement::x1() const
|
|
{
|
|
auto& value = get(PropertyID::X1);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length LineElement::y1() const
|
|
{
|
|
auto& value = get(PropertyID::Y1);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length LineElement::x2() const
|
|
{
|
|
auto& value = get(PropertyID::X2);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length LineElement::y2() const
|
|
{
|
|
auto& value = get(PropertyID::Y2);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Path LineElement::path() const
|
|
{
|
|
LengthContext lengthContext(this);
|
|
auto _x1 = lengthContext.valueForLength(x1(), LengthMode::Width);
|
|
auto _y1 = lengthContext.valueForLength(y1(), LengthMode::Height);
|
|
auto _x2 = lengthContext.valueForLength(x2(), LengthMode::Width);
|
|
auto _y2 = lengthContext.valueForLength(y2(), LengthMode::Height);
|
|
|
|
Path path;
|
|
path.moveTo(_x1, _y1);
|
|
path.lineTo(_x2, _y2);
|
|
return path;
|
|
}
|
|
|
|
std::unique_ptr<Node> LineElement::clone() const
|
|
{
|
|
return cloneElement<LineElement>();
|
|
}
|
|
|
|
RectElement::RectElement()
|
|
: GeometryElement(ElementID::Rect)
|
|
{
|
|
}
|
|
|
|
Length RectElement::x() const
|
|
{
|
|
auto& value = get(PropertyID::X);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length RectElement::y() const
|
|
{
|
|
auto& value = get(PropertyID::Y);
|
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length RectElement::rx() const
|
|
{
|
|
auto& value = get(PropertyID::Rx);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
|
}
|
|
|
|
Length RectElement::ry() const
|
|
{
|
|
auto& value = get(PropertyID::Ry);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
|
}
|
|
|
|
Length RectElement::width() const
|
|
{
|
|
auto& value = get(PropertyID::Width);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Length RectElement::height() const
|
|
{
|
|
auto& value = get(PropertyID::Height);
|
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
|
}
|
|
|
|
Path RectElement::path() const
|
|
{
|
|
auto w = this->width();
|
|
auto h = this->height();
|
|
if(w.isZero() || h.isZero())
|
|
return Path{};
|
|
|
|
LengthContext lengthContext(this);
|
|
auto _x = lengthContext.valueForLength(x(), LengthMode::Width);
|
|
auto _y = lengthContext.valueForLength(y(), LengthMode::Height);
|
|
auto _w = lengthContext.valueForLength(w, LengthMode::Width);
|
|
auto _h = lengthContext.valueForLength(h, LengthMode::Height);
|
|
|
|
auto rx = this->rx();
|
|
auto ry = this->ry();
|
|
|
|
auto _rx = lengthContext.valueForLength(rx, LengthMode::Width);
|
|
auto _ry = lengthContext.valueForLength(ry, LengthMode::Height);
|
|
|
|
if(!rx.isValid()) _rx = _ry;
|
|
if(!ry.isValid()) _ry = _rx;
|
|
|
|
Path path;
|
|
path.rect(_x, _y, _w, _h, _rx, _ry);
|
|
return path;
|
|
}
|
|
|
|
std::unique_ptr<Node> RectElement::clone() const
|
|
{
|
|
return cloneElement<RectElement>();
|
|
}
|
|
|
|
} // namespace lunasvg
|