kopia lustrzana https://github.com/jameshball/osci-render
Add code for SvgState, MoveTo, LineTo, CurveTo, ClosePath
rodzic
f0e99440fc
commit
60b80b7812
|
@ -31,6 +31,11 @@ void Vector2::translate(double x, double y) {
|
|||
this->y += y;
|
||||
}
|
||||
|
||||
void Vector2::reflectRelativeToVector(double x, double y) {
|
||||
this->x += 2.0 * (x - this->x);
|
||||
this->y += 2.0 * (y - this->y);
|
||||
}
|
||||
|
||||
double Vector2::length() {
|
||||
return 0.0;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public:
|
|||
void rotate(double theta);
|
||||
void scale(double x, double y);
|
||||
void translate(double x, double y);
|
||||
void reflectRelativeToVector(double x, double y);
|
||||
double length();
|
||||
|
||||
double x, y;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include "ClosePath.h"
|
||||
#include "../shape/Line.h"
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> ClosePath::absolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseClosePath(state, args);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> ClosePath::relative(SvgState& state, std::vector<float>& args) {
|
||||
return parseClosePath(state, args);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> ClosePath::parseClosePath(SvgState& state, std::vector<float>& args) {
|
||||
auto shapes = std::vector<std::unique_ptr<Shape>>();
|
||||
if (state.currPoint.x != state.initialPoint.x || state.currPoint.y != state.initialPoint.y) {
|
||||
state.currPoint = state.initialPoint;
|
||||
shapes.push_back(std::make_unique<Line>(state.currPoint.x, state.currPoint.y, state.initialPoint.x, state.initialPoint.y));
|
||||
}
|
||||
return shapes;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "../shape/Shape.h"
|
||||
#include "SvgState.h"
|
||||
|
||||
class ClosePath {
|
||||
public:
|
||||
static std::vector<std::unique_ptr<Shape>> absolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> relative(SvgState& state, std::vector<float>& args);
|
||||
private:
|
||||
static std::vector<std::unique_ptr<Shape>> parseClosePath(SvgState& state, std::vector<float>& args);
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
#include "CurveTo.h"
|
||||
#include "../shape/CubicBezierCurve.h"
|
||||
#include "../shape/QuadraticBezierCurve.h"
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::absolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, true, true, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::relative(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, false, true, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::smoothAbsolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, true, true, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::smoothRelative(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, false, true, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::quarticAbsolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, true, false, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::quarticRelative(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, false, false, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::quarticSmoothAbsolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, true, false, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::quarticSmoothRelative(SvgState& state, std::vector<float>& args) {
|
||||
return parseCurveTo(state, args, false, false, true);
|
||||
}
|
||||
|
||||
|
||||
// Parses curveto commands (C, c, S, s, Q, q, T, and t commands)
|
||||
// isCubic should be true for parsing C, c, S, and s commands
|
||||
// isCubic should be false for parsing Q, q, T, and t commands
|
||||
// isSmooth should be true for parsing S, s, T, and t commands
|
||||
// isSmooth should be false for parsing C, c, Q, and q commands
|
||||
std::vector<std::unique_ptr<Shape>> CurveTo::parseCurveTo(SvgState& state, std::vector<float>& args, bool isAbsolute, bool isCubic, bool isSmooth) {
|
||||
int expectedArgs = isCubic ? 4 : 2;
|
||||
if (!isSmooth) {
|
||||
expectedArgs += 2;
|
||||
}
|
||||
|
||||
if (args.size() % expectedArgs != 0 || args.size() < expectedArgs) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto curves = std::vector<std::unique_ptr<Shape>>();
|
||||
|
||||
for (int i = 0; i < args.size(); i += expectedArgs) {
|
||||
Vector2 controlPoint1;
|
||||
Vector2 controlPoint2;
|
||||
|
||||
if (isSmooth) {
|
||||
if (isCubic) {
|
||||
if (!state.prevCubicControlPoint.has_value()) {
|
||||
controlPoint1 = state.currPoint;
|
||||
} else {
|
||||
controlPoint1 = state.prevCubicControlPoint.value();
|
||||
controlPoint1.reflectRelativeToVector(state.currPoint.x, state.currPoint.y);
|
||||
}
|
||||
} else {
|
||||
if (!state.prevQuadraticControlPoint.has_value()) {
|
||||
controlPoint1 = state.currPoint;
|
||||
} else {
|
||||
controlPoint1 = state.prevQuadraticControlPoint.value();
|
||||
controlPoint1.reflectRelativeToVector(state.currPoint.x, state.currPoint.y);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
controlPoint1 = Vector2(args[i], args[i + 1]);
|
||||
}
|
||||
|
||||
if (isCubic) {
|
||||
controlPoint2 = Vector2(args[i + 2], args[i + 3]);
|
||||
}
|
||||
|
||||
Vector2 newPoint(args[i + expectedArgs - 2], args[i + expectedArgs - 1]);
|
||||
|
||||
if (!isAbsolute) {
|
||||
controlPoint1.translate(state.currPoint.x, state.currPoint.y);
|
||||
controlPoint2.translate(state.currPoint.x, state.currPoint.y);
|
||||
newPoint.translate(state.currPoint.x, state.currPoint.y);
|
||||
}
|
||||
|
||||
if (isCubic) {
|
||||
curves.push_back(std::make_unique<CubicBezierCurve>(state.currPoint.x, state.currPoint.y, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, newPoint.x, newPoint.y));
|
||||
state.currPoint = newPoint;
|
||||
state.prevCubicControlPoint = controlPoint2;
|
||||
} else {
|
||||
curves.push_back(std::make_unique<QuadraticBezierCurve>(state.currPoint.x, state.currPoint.y, controlPoint1.x, controlPoint1.y, newPoint.x, newPoint.y));
|
||||
state.currPoint = newPoint;
|
||||
state.prevQuadraticControlPoint = controlPoint1;
|
||||
}
|
||||
}
|
||||
|
||||
return curves;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "../shape/Shape.h"
|
||||
#include "SvgState.h"
|
||||
|
||||
class CurveTo {
|
||||
public:
|
||||
static std::vector<std::unique_ptr<Shape>> absolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> relative(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> smoothAbsolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> smoothRelative(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> quarticAbsolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> quarticRelative(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> quarticSmoothAbsolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> quarticSmoothRelative(SvgState& state, std::vector<float>& args);
|
||||
private:
|
||||
static std::vector<std::unique_ptr<Shape>> parseCurveTo(SvgState& state, std::vector<float>& args, bool isAbsolute, bool isCubic, bool isSmooth);
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
#include "EllipticalArcTo.h"
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> EllipticalArcTo::absolute(SvgState& state, std::vector<float>& args) {
|
||||
return std::vector<std::unique_ptr<Shape>>();
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> EllipticalArcTo::relative(SvgState& state, std::vector<float>& args) {
|
||||
return std::vector<std::unique_ptr<Shape>>();
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> EllipticalArcTo::parseEllipticalArc(SvgState& state, std::vector<float>& args, bool isAbsolute) {
|
||||
return std::vector<std::unique_ptr<Shape>>();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "../shape/Shape.h"
|
||||
#include "SvgState.h"
|
||||
|
||||
class EllipticalArcTo {
|
||||
public:
|
||||
static std::vector<std::unique_ptr<Shape>> absolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> relative(SvgState& state, std::vector<float>& args);
|
||||
private:
|
||||
static std::vector<std::unique_ptr<Shape>> parseEllipticalArc(SvgState& state, std::vector<float>& args, bool isAbsolute);
|
||||
};
|
|
@ -0,0 +1,74 @@
|
|||
#include "LineTo.h"
|
||||
#include "../shape/Line.h"
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::absolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseLineTo(state, args, true, true, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::relative(SvgState& state, std::vector<float>& args) {
|
||||
return parseLineTo(state, args, false, true, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::horizontalAbsolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseLineTo(state, args, true, true, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::horizontalRelative(SvgState& state, std::vector<float>& args) {
|
||||
return parseLineTo(state, args, false, true, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::verticalAbsolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseLineTo(state, args, true, false, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::verticalRelative(SvgState& state, std::vector<float>& args) {
|
||||
return parseLineTo(state, args, false, false, true);
|
||||
}
|
||||
|
||||
|
||||
// Parses lineto commands (L, l, H, h, V, and v commands)
|
||||
// isHorizontal and isVertical should be true for parsing L and l commands
|
||||
// Only isHorizontal should be true for parsing H and h commands
|
||||
// Only isVertical should be true for parsing V and v commands
|
||||
std::vector<std::unique_ptr<Shape>> LineTo::parseLineTo(SvgState& state, std::vector<float>& args, bool isAbsolute, bool isHorizontal, bool isVertical) {
|
||||
int expectedArgs = isHorizontal && isVertical ? 2 : 1;
|
||||
|
||||
if (args.size() % expectedArgs != 0 || args.size() < expectedArgs) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto lines = std::vector<std::unique_ptr<Shape>>();
|
||||
|
||||
for (int i = 0; i < args.size(); i += expectedArgs) {
|
||||
Vector2 newPoint;
|
||||
|
||||
if (expectedArgs == 1) {
|
||||
newPoint = Vector2(args[i], args[i]);
|
||||
} else {
|
||||
newPoint = Vector2(args[i], args[i + 1]);
|
||||
}
|
||||
|
||||
if (isHorizontal && !isVertical) {
|
||||
if (isAbsolute) {
|
||||
newPoint.y = state.currPoint.y;
|
||||
} else {
|
||||
newPoint.y = 0;
|
||||
}
|
||||
} else if (isVertical && !isHorizontal) {
|
||||
if (isAbsolute) {
|
||||
newPoint.x = state.currPoint.x;
|
||||
} else {
|
||||
newPoint.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAbsolute) {
|
||||
newPoint.translate(state.currPoint.x, state.currPoint.y);
|
||||
}
|
||||
|
||||
lines.push_back(std::make_unique<Line>(state.currPoint.x, state.currPoint.y, newPoint.x, newPoint.y));
|
||||
state.currPoint = newPoint;
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "../shape/Shape.h"
|
||||
#include "SvgState.h"
|
||||
|
||||
class LineTo {
|
||||
public:
|
||||
static std::vector<std::unique_ptr<Shape>> absolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> relative(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> horizontalAbsolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> horizontalRelative(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> verticalAbsolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> verticalRelative(SvgState& state, std::vector<float>& args);
|
||||
private:
|
||||
static std::vector<std::unique_ptr<Shape>> parseLineTo(SvgState& state, std::vector<float>& args, bool isAbsolute, bool isHorizontal, bool isVertical);
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
#include "MoveTo.h"
|
||||
#include "LineTo.h"
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> MoveTo::absolute(SvgState& state, std::vector<float>& args) {
|
||||
return parseMoveTo(state, args, true);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> MoveTo::relative(SvgState& state, std::vector<float>& args) {
|
||||
return parseMoveTo(state, args, false);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> MoveTo::parseMoveTo(SvgState& state, std::vector<float>& args, bool isAbsolute) {
|
||||
if (args.size() % 2 != 0 || args.size() < 2) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Vector2 vec(args[0], args[1]);
|
||||
|
||||
if (isAbsolute) {
|
||||
state.currPoint = vec;
|
||||
state.initialPoint = state.currPoint;
|
||||
if (args.size() > 2) {
|
||||
std::vector<float> newArgs = std::vector<float>(args.begin() + 2, args.end());
|
||||
return LineTo::absolute(state, newArgs);
|
||||
}
|
||||
} else {
|
||||
state.currPoint.translate(vec.x, vec.y);
|
||||
state.initialPoint = state.currPoint;
|
||||
if (args.size() > 2) {
|
||||
std::vector<float> newArgs = std::vector<float>(args.begin() + 2, args.end());
|
||||
return LineTo::relative(state, newArgs);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "../shape/Shape.h"
|
||||
#include "SvgState.h"
|
||||
|
||||
class MoveTo {
|
||||
public:
|
||||
static std::vector<std::unique_ptr<Shape>> absolute(SvgState& state, std::vector<float>& args);
|
||||
static std::vector<std::unique_ptr<Shape>> relative(SvgState& state, std::vector<float>& args);
|
||||
private:
|
||||
static std::vector<std::unique_ptr<Shape>> parseMoveTo(SvgState& state, std::vector<float>& args, bool isAbsolute);
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
#include "SvgState.h"
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
#include "../shape/Vector2.h"
|
||||
|
||||
struct {
|
||||
Vector2 currPoint;
|
||||
Vector2 initialPoint;
|
||||
Vector2 prevCubicControlPoint;
|
||||
Vector2 prevQuadraticControlPoint;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
#include "SvgState.h"
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
#include "../shape/Vector2.h"
|
||||
#include <optional>
|
||||
|
||||
struct SvgState {
|
||||
Vector2 currPoint;
|
||||
Vector2 initialPoint;
|
||||
std::optional<Vector2> prevCubicControlPoint;
|
||||
std::optional<Vector2> prevQuadraticControlPoint;
|
||||
};
|
|
@ -7,6 +7,24 @@
|
|||
cppLanguageStandard="20" projectLineFeed=" " headerPath="./include">
|
||||
<MAINGROUP id="j5Ge2T" name="osci-render">
|
||||
<GROUP id="{75439074-E50C-362F-1EDF-8B4BE9011259}" name="Source">
|
||||
<GROUP id="{56A27063-1FE7-31C3-8263-98389240A8CB}" name="svg">
|
||||
<FILE id="FVWkba" name="ClosePath.cpp" compile="1" resource="0" file="Source/svg/ClosePath.cpp"/>
|
||||
<FILE id="pJz3ek" name="ClosePath.h" compile="0" resource="0" file="Source/svg/ClosePath.h"/>
|
||||
<FILE id="PS8Qfk" name="CurveTo.cpp" compile="1" resource="0" file="Source/svg/CurveTo.cpp"/>
|
||||
<FILE id="Sjh7ne" name="CurveTo.h" compile="0" resource="0" file="Source/svg/CurveTo.h"/>
|
||||
<FILE id="DQJJdr" name="EllipticalArcTo.cpp" compile="1" resource="0"
|
||||
file="Source/svg/EllipticalArcTo.cpp"/>
|
||||
<FILE id="iVMpEw" name="EllipticalArcTo.h" compile="0" resource="0"
|
||||
file="Source/svg/EllipticalArcTo.h"/>
|
||||
<FILE id="DSmqNL" name="LineTo.cpp" compile="1" resource="0" file="Source/svg/LineTo.cpp"/>
|
||||
<FILE id="fjo7Oy" name="LineTo.h" compile="0" resource="0" file="Source/svg/LineTo.h"/>
|
||||
<FILE id="c2y2ap" name="MoveTo.cpp" compile="1" resource="0" file="Source/svg/MoveTo.cpp"/>
|
||||
<FILE id="SfIJEj" name="MoveTo.h" compile="0" resource="0" file="Source/svg/MoveTo.h"/>
|
||||
<FILE id="cTec1H" name="SvgParser.cpp" compile="1" resource="0" file="Source/svg/SvgParser.cpp"/>
|
||||
<FILE id="gvkrDH" name="SvgParser.h" compile="0" resource="0" file="Source/svg/SvgParser.h"/>
|
||||
<FILE id="OvloZU" name="SvgState.cpp" compile="1" resource="0" file="Source/svg/SvgState.cpp"/>
|
||||
<FILE id="GCBO9x" name="SvgState.h" compile="0" resource="0" file="Source/svg/SvgState.h"/>
|
||||
</GROUP>
|
||||
<GROUP id="{2A41BAF3-5E83-B018-5668-39D89ABFA00C}" name="chinese_postman">
|
||||
<FILE id="LcDpwe" name="BinaryHeap.cpp" compile="1" resource="0" file="Source/chinese_postman/BinaryHeap.cpp"/>
|
||||
<FILE id="UYdaXR" name="BinaryHeap.h" compile="0" resource="0" file="Source/chinese_postman/BinaryHeap.h"/>
|
||||
|
|
Ładowanie…
Reference in New Issue