#include "CurveTo.h" #include "../shape/CubicBezierCurve.h" #include "../shape/QuadraticBezierCurve.h" std::vector> CurveTo::absolute(SvgState& state, std::vector& args) { return parseCurveTo(state, args, true, true, false); } std::vector> CurveTo::relative(SvgState& state, std::vector& args) { return parseCurveTo(state, args, false, true, false); } std::vector> CurveTo::smoothAbsolute(SvgState& state, std::vector& args) { return parseCurveTo(state, args, true, true, true); } std::vector> CurveTo::smoothRelative(SvgState& state, std::vector& args) { return parseCurveTo(state, args, false, true, true); } std::vector> CurveTo::quarticAbsolute(SvgState& state, std::vector& args) { return parseCurveTo(state, args, true, false, false); } std::vector> CurveTo::quarticRelative(SvgState& state, std::vector& args) { return parseCurveTo(state, args, false, false, false); } std::vector> CurveTo::quarticSmoothAbsolute(SvgState& state, std::vector& args) { return parseCurveTo(state, args, true, false, true); } std::vector> CurveTo::quarticSmoothRelative(SvgState& state, std::vector& 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> CurveTo::parseCurveTo(SvgState& state, std::vector& 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>(); 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(); } } else { if (!state.prevQuadraticControlPoint.has_value()) { controlPoint1 = state.currPoint; } else { controlPoint1 = state.prevQuadraticControlPoint.value(); } } } else { controlPoint1 = Vector2(args[i], args[i + 1]); } if (isCubic) { controlPoint2 = Vector2(args[i + expectedArgs - 4], args[i + expectedArgs - 3]); } Vector2 newPoint(args[i + expectedArgs - 2], args[i + expectedArgs - 1]); if (!isAbsolute) { if (!isSmooth) { 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 (isSmooth) { controlPoint1.reflectRelativeToVector(state.currPoint.x, state.currPoint.y); } if (isCubic) { curves.push_back(std::make_unique(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(state.currPoint.x, state.currPoint.y, controlPoint1.x, controlPoint1.y, newPoint.x, newPoint.y)); state.currPoint = newPoint; state.prevQuadraticControlPoint = controlPoint1; } } return curves; }