From 25bc2fb2807303005228316bd784512062c351bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=B0=81=E7=BE=BD?= <2360164671@qq.com> Date: Tue, 11 Oct 2022 19:57:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E6=A4=AD=E5=9C=86?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 2 +- ArchitectureColoredPainting/SvgParser.cpp | 1273 +++++++++-------- ArchitectureColoredPainting/SvgParser.h | 295 ++-- 3 files changed, 881 insertions(+), 689 deletions(-) diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 334afac..c8babd2 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -31,7 +31,7 @@ - 5.15.2_msvc2019_64 + 5.15.0_msvc2019_64 core;gui;widgets debug diff --git a/ArchitectureColoredPainting/SvgParser.cpp b/ArchitectureColoredPainting/SvgParser.cpp index b5b7760..bfc33e1 100644 --- a/ArchitectureColoredPainting/SvgParser.cpp +++ b/ArchitectureColoredPainting/SvgParser.cpp @@ -3,592 +3,751 @@ #include using namespace std; -namespace SVGParser { +namespace SVGParser +{ - SVGCommandType getSVGCommand(char c) { - switch (c) { - case 'm': - return SVG_MOVE_TO_REL; - break; - case 'M': - return SVG_MOVE_TO_ABS; - break; +SVGCommandType getSVGCommand(char c) +{ + switch (c) + { + case 'm': + return SVG_MOVE_TO_REL; + break; + case 'M': + return SVG_MOVE_TO_ABS; + break; - case 'l': - return SVG_LINE_TO_REL; - break; - case 'L': - return SVG_LINE_TO_ABS; - break; + case 'l': + return SVG_LINE_TO_REL; + break; + case 'L': + return SVG_LINE_TO_ABS; + break; - case 'c': - return SVG_CUBIC_CURVE_TO_REL; - break; - case 'C': - return SVG_CUBIC_CURVE_TO_ABS; - break; + case 'c': + return SVG_CUBIC_CURVE_TO_REL; + break; + case 'C': + return SVG_CUBIC_CURVE_TO_ABS; + break; - case 'q': - return SVG_QUADRATIC_CURVE_TO_REL; - break; - case 'Q': - return SVG_QUADRATIC_CURVE_TO_ABS; - break; + case 'q': + return SVG_QUADRATIC_CURVE_TO_REL; + break; + case 'Q': + return SVG_QUADRATIC_CURVE_TO_ABS; + break; - case 'a': - return SVG_ARC_TO_REL; - break; - case 'A': - return SVG_ARC_TO_ABS; - break; + case 'a': + return SVG_ARC_TO_REL; + break; + case 'A': + return SVG_ARC_TO_ABS; + break; - case 't': - return SVG_SMOOTH_QUADRATIC_CURVE_TO_REL; - break; - case 'T': - return SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS; - break; + case 't': + return SVG_SMOOTH_QUADRATIC_CURVE_TO_REL; + break; + case 'T': + return SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS; + break; - case 's': - return SVG_SMOOTH_CUBIC_CURVE_TO_REL; - break; - case 'S': - return SVG_SMOOTH_CUBIC_CURVE_TO_ABS; - break; + case 's': + return SVG_SMOOTH_CUBIC_CURVE_TO_REL; + break; + case 'S': + return SVG_SMOOTH_CUBIC_CURVE_TO_ABS; + break; - case 'h': - return SVG_HORIZONTAL_LINE_TO_REL; - break; - case 'H': - return SVG_HORIZONTAL_LINE_TO_ABS; - break; + case 'h': + return SVG_HORIZONTAL_LINE_TO_REL; + break; + case 'H': + return SVG_HORIZONTAL_LINE_TO_ABS; + break; - case 'v': - return SVG_VERTICAL_LINE_TO_REL; - break; - case 'V': - return SVG_VERTICAL_LINE_TO_ABS; - break; - - case 'z': - case 'Z': - return SVG_CLOSE_PATH; - break; - default: - return SVG_INVALID; - break; - } - }; - int getCommandLength(SVGCommandType t) { - switch (t) { - case SVG_MOVE_TO_REL: - case SVG_LINE_TO_REL: - case SVG_MOVE_TO_ABS: - case SVG_LINE_TO_ABS: - return 2; - break; - case SVG_HORIZONTAL_LINE_TO_REL: - case SVG_HORIZONTAL_LINE_TO_ABS: - case SVG_VERTICAL_LINE_TO_REL: - case SVG_VERTICAL_LINE_TO_ABS: - return 1; - break; - - - case SVG_QUADRATIC_CURVE_TO_REL: - case SVG_QUADRATIC_CURVE_TO_ABS: - return 4; - break; - case SVG_CUBIC_CURVE_TO_REL: - case SVG_CUBIC_CURVE_TO_ABS: - return 6; - break; - - case SVG_SMOOTH_CUBIC_CURVE_TO_REL: - case SVG_SMOOTH_CUBIC_CURVE_TO_ABS: - return 4; - break; - - case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL: - case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS: - return 2; - break; - - case SVG_ARC_TO_REL: - case SVG_ARC_TO_ABS: - return 7; - break; - case SVG_CLOSE_PATH: - case SVG_INVALID: - default: - return 0; - break; - } - }; - bool isAbsolute(SVGCommandType t) { - if (t == SVG_CLOSE_PATH) return false; - return t % 2; - } - SVGPath createCommandChunk(SVGCommandType t, vector elements) { - int commandLength = getCommandLength(t); - SVGPath chunk; - bool abs = isAbsolute(t); - if (t == SVG_CLOSE_PATH) chunk.push_back(make_shared()); - if (commandLength > 0) - for (int i = 0; i < int(elements.size() / commandLength); i++) { - switch (t) { - case SVG_LINE_TO_REL: - case SVG_LINE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs)); - break; - case SVG_MOVE_TO_REL: - case SVG_MOVE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs)); - break; - case SVG_CUBIC_CURVE_TO_REL: - case SVG_CUBIC_CURVE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], - elements[i * commandLength + 2], elements[i * commandLength + 3], - elements[i * commandLength + 4], elements[i * commandLength + 5], abs)); - break; - - case SVG_SMOOTH_CUBIC_CURVE_TO_REL: - case SVG_SMOOTH_CUBIC_CURVE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], - elements[i * commandLength + 2], elements[i * commandLength + 3], abs)); - break; - - case SVG_QUADRATIC_CURVE_TO_REL: - case SVG_QUADRATIC_CURVE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], - elements[i * commandLength + 2], elements[i * commandLength + 3], abs)); - break; - - case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL: - case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs)); - break; - - case SVG_ARC_TO_REL: - case SVG_ARC_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1],//rx, ry - elements[i * commandLength + 2],//rotation, - int(elements[i * commandLength + 3]) == 1, int(elements[i * commandLength + 4]) == 1, //large arc, sweep - elements[i * commandLength + 5], elements[i * commandLength + 6], //end x, end y - abs)); - break; - case SVG_HORIZONTAL_LINE_TO_REL: - case SVG_HORIZONTAL_LINE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], abs)); - break; - case SVG_VERTICAL_LINE_TO_REL: - case SVG_VERTICAL_LINE_TO_ABS: - chunk.push_back(make_shared(elements[i * commandLength + 0], abs)); - break; - } - //This here is funky. - if (t == SVG_MOVE_TO_REL || t == SVG_MOVE_TO_ABS) t = SVGCommandType(int(t) + 2); - } - return chunk; - } - SVGPath parsePath(istream& ss) { - SVGPath commandArray; - //istringstream ss(path); - //bool absolute = false; - SVGCommandType command = SVG_INVALID; - vector elements; - - while (ss.good()) { - char c = ss.get(); - SVGCommandType cmd = getSVGCommand(c); - - if (cmd != SVG_INVALID) { - SVGPath chunk = createCommandChunk(command, elements); - commandArray.insert(commandArray.end(), chunk.begin(), chunk.end()); - command = cmd; - elements.clear(); - - } - else if (!(isspace(c) || c == ',')) {//its a number... - double x; - ss.unget(); - ss >> x; - elements.push_back(x); - }// else its a separator - } - SVGPath chunk = createCommandChunk(command, elements); - commandArray.insert(commandArray.end(), chunk.begin(), chunk.end()); - return commandArray; - } - - SVGCommand::SVGCommand(double _x, double _y, bool abs) : x(_x), y(_y), absolute(abs) {} - SVGLineTo::SVGLineTo(double x, double y, bool abs) : SVGCommand(x, y, abs) { - } - - const string SVGLineTo::toString() const { - stringstream s; - s << (absolute ? "L" : "l") << x << "," << y; - return s.str(); - } - string SVGLineTo::toString2() { - stringstream s; - s << "Line to (" << (absolute ? "absolute" : "relative") << ") " << x << "x" << y; - return s.str(); - } - - SVGCommandType SVGLineTo::getType() { - return absolute ? SVG_LINE_TO_ABS : SVG_LINE_TO_REL; - } - - SVGHLineTo::SVGHLineTo(double x, bool abs) : SVGCommand(x, 0, abs) { - } - const string SVGHLineTo::toString() const { - stringstream s; - s << (absolute ? "H" : "h") << x; - return s.str(); - } - string SVGHLineTo::toString2() { - stringstream s; - s << "Horizontal Line (" << (absolute ? "absolute" : "relative") << ") " << x << "px"; - return s.str(); - } - - SVGCommandType SVGHLineTo::getType() { - return absolute ? SVG_HORIZONTAL_LINE_TO_ABS : SVG_HORIZONTAL_LINE_TO_REL; - } - - SVGVLineTo::SVGVLineTo(double y, bool abs) : SVGCommand(0, y, abs) { - } - - const string SVGVLineTo::toString() const { - stringstream s; - s << (absolute ? "V" : "v") << y; - return s.str(); - } - string SVGVLineTo::toString2() { - stringstream s; - s << "Vertical Line (" << (absolute ? "absolute" : "relative") << ") " << y << "px"; - return s.str(); - } - SVGCommandType SVGVLineTo::getType() { - return absolute ? SVG_VERTICAL_LINE_TO_ABS : SVG_VERTICAL_LINE_TO_REL; - } - - - - - SVGMoveTo::SVGMoveTo(double x, double y, bool abs) : SVGCommand(x, y, abs) { - } - const string SVGMoveTo::toString() const { - stringstream s; - s << (absolute ? "M" : "m") << x << "," << y; - return s.str(); - } - string SVGMoveTo::toString2() { - stringstream s; - s << "Move to (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y; - return s.str(); - } - SVGCommandType SVGMoveTo::getType() { - return absolute ? SVG_MOVE_TO_ABS : SVG_MOVE_TO_REL; - } - - - SVGCubicCurveTo::SVGCubicCurveTo(double _x0, double _y0, - double _x1, double _y1, - double x, double y, bool abs) : SVGCommand(x, y, abs), - x0(_x0), y0(_y0), - x1(_x1), y1(_y1) { - } - - const string SVGCubicCurveTo::toString() const { - stringstream s; - s << (absolute ? "C" : "c") << x0 << "," << y0 << " " << x1 << "," << y1 << " " << x << "," << y; - return s.str(); - } - string SVGCubicCurveTo::toString2() { - stringstream s; - s << "Cubic Curve (" << (absolute ? "absolute" : "relative") << ") control points: " << x0 << "," << y0 << " " << x1 << "," << y1 << " to " << x << "x" << y; - return s.str(); - } - SVGCommandType SVGCubicCurveTo::getType() { - return absolute ? SVG_CUBIC_CURVE_TO_ABS : SVG_CUBIC_CURVE_TO_REL; - } - - SVGSmoothCubicCurveTo::SVGSmoothCubicCurveTo( - double _x1, double _y1, - double x, double y, bool abs) : SVGCommand(x, y, abs), - x1(_x1), y1(_y1) { - } - - const string SVGSmoothCubicCurveTo::toString() const { - stringstream s; - s << (absolute ? "S" : "s") << x1 << "," << y1 << " " << x << "," << y; - return s.str(); - } - string SVGSmoothCubicCurveTo::toString2() { - stringstream s; - s << "Smooth cubic curve to (" << (absolute ? "absolute" : "relative") << ") control point: " << x1 << "," << y1 << " to " << x << "x" << y; - return s.str(); - } - SVGCommandType SVGSmoothCubicCurveTo::getType() { - return absolute ? SVG_SMOOTH_CUBIC_CURVE_TO_ABS : SVG_SMOOTH_CUBIC_CURVE_TO_REL; - } - - - SVGQuadraticCurveTo::SVGQuadraticCurveTo(double _x0, double _y0, - double x, double y, bool abs) : SVGCommand(x, y, abs), x0(_x0), y0(_y0) { - } - const string SVGQuadraticCurveTo::toString() const { - stringstream s; - s << (absolute ? "Q" : "q") << x0 << "," << y0 << " " << x << "," << y; - return s.str(); - } - string SVGQuadraticCurveTo::toString2() { - stringstream s; - s << "quadratic curve (" << (absolute ? "absolute" : "relative") << ") control point: " << x0 << "," << y0 << " to " << x << "x" << y; - return s.str(); - } - SVGCommandType SVGQuadraticCurveTo::getType() { - return absolute ? SVG_QUADRATIC_CURVE_TO_ABS : SVG_QUADRATIC_CURVE_TO_REL; - } - SVGSmoothQuadraticCurveTo::SVGSmoothQuadraticCurveTo( - double x, double y, bool abs) : SVGCommand(x, y, abs) { - } - const string SVGSmoothQuadraticCurveTo::toString() const { - stringstream s; - s << (absolute ? "T" : "t") << x << "," << y; - return s.str(); - } - string SVGSmoothQuadraticCurveTo::toString2() { - stringstream s; - s << "Smooth quadratic curve (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y; - return s.str(); - } - SVGCommandType SVGSmoothQuadraticCurveTo::getType() { - return absolute ? SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS : SVG_SMOOTH_QUADRATIC_CURVE_TO_REL; - } - - SVGArcTo::SVGArcTo(double rx, double ry, double rotxaxis, bool large, bool sweep, double x, double y, bool abs) : SVGCommand(x, y, abs) { - this->rx = rx; - this->ry = ry; - - this->rot = rotxaxis; - - this->large = large; - this->sweep = sweep; - } - const string SVGArcTo::toString() const { - stringstream s; - s << (absolute ? "A" : "a") << rx << "," << ry << " " << rot << " " << large << "," << sweep << " " << x << "," << y; - return s.str(); - } - - string SVGArcTo::toString2() { - stringstream s; - s << "Arc (" << (absolute ? "absolute" : "relative") << "x-radii: " << rx << " y-radii: " << ry << " x-rotation: " << rot << " large-arc: " << large << " sweep: " << sweep << " to: " << x << "x" << y; - return s.str(); - } - - SVGCommandType SVGArcTo::getType() { - return absolute ? SVG_ARC_TO_ABS : SVG_ARC_TO_REL; - } - - SVGClosePath::SVGClosePath(bool abs) :SVGCommand(0, 0, abs) { - - } - - const string SVGClosePath::toString() const { - stringstream s; - s << (absolute ? "Z" : "z"); - return s.str(); - } - string SVGClosePath::toString2() { - stringstream s; - s << "Close path"; - return s.str(); - } - SVGCommandType SVGClosePath::getType() { - return SVG_CLOSE_PATH; - } - std::ostream& operator<< (std::ostream& out, const SVGParser::SVGPath& path) { - for (SVGParser::SVGPath::const_iterator it = path.begin(); it != path.end(); it++) { - out << (*it)->toString(); - } - return out; - } - std::ostream& operator<< (std::ostream& out, const SVGParser::SVGCommand* cmd) { - out << cmd->toString(); - return out; - } + case 'v': + return SVG_VERTICAL_LINE_TO_REL; + break; + case 'V': + return SVG_VERTICAL_LINE_TO_ABS; + break; + case 'z': + case 'Z': + return SVG_CLOSE_PATH; + break; + default: + return SVG_INVALID; + break; + } }; +int getCommandLength(SVGCommandType t) +{ + switch (t) + { + case SVG_MOVE_TO_REL: + case SVG_LINE_TO_REL: + case SVG_MOVE_TO_ABS: + case SVG_LINE_TO_ABS: + return 2; + break; + case SVG_HORIZONTAL_LINE_TO_REL: + case SVG_HORIZONTAL_LINE_TO_ABS: + case SVG_VERTICAL_LINE_TO_REL: + case SVG_VERTICAL_LINE_TO_ABS: + return 1; + break; -SvgParser::SvgParser(const std::string path, double width, double height) :path(path), width(width), height(height) + case SVG_QUADRATIC_CURVE_TO_REL: + case SVG_QUADRATIC_CURVE_TO_ABS: + return 4; + break; + case SVG_CUBIC_CURVE_TO_REL: + case SVG_CUBIC_CURVE_TO_ABS: + return 6; + break; + + case SVG_SMOOTH_CUBIC_CURVE_TO_REL: + case SVG_SMOOTH_CUBIC_CURVE_TO_ABS: + return 4; + break; + + case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL: + case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS: + return 2; + break; + + case SVG_ARC_TO_REL: + case SVG_ARC_TO_ABS: + return 7; + break; + case SVG_CLOSE_PATH: + case SVG_INVALID: + default: + return 0; + break; + } +}; +bool isAbsolute(SVGCommandType t) +{ + if (t == SVG_CLOSE_PATH) + return false; + return t % 2; +} +SVGPath createCommandChunk(SVGCommandType t, vector elements) +{ + int commandLength = getCommandLength(t); + SVGPath chunk; + bool abs = isAbsolute(t); + if (t == SVG_CLOSE_PATH) + chunk.push_back(make_shared()); + if (commandLength > 0) + for (int i = 0; i < int(elements.size() / commandLength); i++) + { + switch (t) + { + case SVG_LINE_TO_REL: + case SVG_LINE_TO_ABS: + chunk.push_back( + make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs)); + break; + case SVG_MOVE_TO_REL: + case SVG_MOVE_TO_ABS: + chunk.push_back( + make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs)); + break; + case SVG_CUBIC_CURVE_TO_REL: + case SVG_CUBIC_CURVE_TO_ABS: + chunk.push_back(make_shared( + elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2], + elements[i * commandLength + 3], elements[i * commandLength + 4], elements[i * commandLength + 5], + abs)); + break; + + case SVG_SMOOTH_CUBIC_CURVE_TO_REL: + case SVG_SMOOTH_CUBIC_CURVE_TO_ABS: + chunk.push_back(make_shared( + elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2], + elements[i * commandLength + 3], abs)); + break; + + case SVG_QUADRATIC_CURVE_TO_REL: + case SVG_QUADRATIC_CURVE_TO_ABS: + chunk.push_back(make_shared( + elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2], + elements[i * commandLength + 3], abs)); + break; + + case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL: + case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS: + chunk.push_back(make_shared(elements[i * commandLength + 0], + elements[i * commandLength + 1], abs)); + break; + + case SVG_ARC_TO_REL: + case SVG_ARC_TO_ABS: + chunk.push_back(make_shared( + elements[i * commandLength + 0], elements[i * commandLength + 1], // rx, ry + elements[i * commandLength + 2], // rotation, + int(elements[i * commandLength + 3]) == 1, + int(elements[i * commandLength + 4]) == 1, // large arc, sweep + elements[i * commandLength + 5], elements[i * commandLength + 6], // end x, end y + abs)); + break; + case SVG_HORIZONTAL_LINE_TO_REL: + case SVG_HORIZONTAL_LINE_TO_ABS: + chunk.push_back(make_shared(elements[i * commandLength + 0], abs)); + break; + case SVG_VERTICAL_LINE_TO_REL: + case SVG_VERTICAL_LINE_TO_ABS: + chunk.push_back(make_shared(elements[i * commandLength + 0], abs)); + break; + } + // This here is funky. + if (t == SVG_MOVE_TO_REL || t == SVG_MOVE_TO_ABS) + t = SVGCommandType(int(t) + 2); + } + return chunk; +} +SVGPath parsePath(istream &ss) +{ + SVGPath commandArray; + // istringstream ss(path); + // bool absolute = false; + SVGCommandType command = SVG_INVALID; + vector elements; + + while (ss.good()) + { + char c = ss.get(); + SVGCommandType cmd = getSVGCommand(c); + + if (cmd != SVG_INVALID) + { + SVGPath chunk = createCommandChunk(command, elements); + commandArray.insert(commandArray.end(), chunk.begin(), chunk.end()); + command = cmd; + elements.clear(); + } + else if (!(isspace(c) || c == ',')) + { // its a number... + double x; + ss.unget(); + ss >> x; + elements.push_back(x); + } // else its a separator + } + SVGPath chunk = createCommandChunk(command, elements); + commandArray.insert(commandArray.end(), chunk.begin(), chunk.end()); + return commandArray; +} + +SVGCommand::SVGCommand(double _x, double _y, bool abs) : x(_x), y(_y), absolute(abs) +{ +} +SVGLineTo::SVGLineTo(double x, double y, bool abs) : SVGCommand(x, y, abs) +{ +} + +const string SVGLineTo::toString() const +{ + stringstream s; + s << (absolute ? "L" : "l") << x << "," << y; + return s.str(); +} +string SVGLineTo::toString2() +{ + stringstream s; + s << "Line to (" << (absolute ? "absolute" : "relative") << ") " << x << "x" << y; + return s.str(); +} + +SVGCommandType SVGLineTo::getType() +{ + return absolute ? SVG_LINE_TO_ABS : SVG_LINE_TO_REL; +} + +SVGHLineTo::SVGHLineTo(double x, bool abs) : SVGCommand(x, 0, abs) +{ +} +const string SVGHLineTo::toString() const +{ + stringstream s; + s << (absolute ? "H" : "h") << x; + return s.str(); +} +string SVGHLineTo::toString2() +{ + stringstream s; + s << "Horizontal Line (" << (absolute ? "absolute" : "relative") << ") " << x << "px"; + return s.str(); +} + +SVGCommandType SVGHLineTo::getType() +{ + return absolute ? SVG_HORIZONTAL_LINE_TO_ABS : SVG_HORIZONTAL_LINE_TO_REL; +} + +SVGVLineTo::SVGVLineTo(double y, bool abs) : SVGCommand(0, y, abs) +{ +} + +const string SVGVLineTo::toString() const +{ + stringstream s; + s << (absolute ? "V" : "v") << y; + return s.str(); +} +string SVGVLineTo::toString2() +{ + stringstream s; + s << "Vertical Line (" << (absolute ? "absolute" : "relative") << ") " << y << "px"; + return s.str(); +} +SVGCommandType SVGVLineTo::getType() +{ + return absolute ? SVG_VERTICAL_LINE_TO_ABS : SVG_VERTICAL_LINE_TO_REL; +} + +SVGMoveTo::SVGMoveTo(double x, double y, bool abs) : SVGCommand(x, y, abs) +{ +} +const string SVGMoveTo::toString() const +{ + stringstream s; + s << (absolute ? "M" : "m") << x << "," << y; + return s.str(); +} +string SVGMoveTo::toString2() +{ + stringstream s; + s << "Move to (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y; + return s.str(); +} +SVGCommandType SVGMoveTo::getType() +{ + return absolute ? SVG_MOVE_TO_ABS : SVG_MOVE_TO_REL; +} + +SVGCubicCurveTo::SVGCubicCurveTo(double _x0, double _y0, double _x1, double _y1, double x, double y, bool abs) + : SVGCommand(x, y, abs), x0(_x0), y0(_y0), x1(_x1), y1(_y1) +{ +} + +const string SVGCubicCurveTo::toString() const +{ + stringstream s; + s << (absolute ? "C" : "c") << x0 << "," << y0 << " " << x1 << "," << y1 << " " << x << "," << y; + return s.str(); +} +string SVGCubicCurveTo::toString2() +{ + stringstream s; + s << "Cubic Curve (" << (absolute ? "absolute" : "relative") << ") control points: " << x0 << "," << y0 << " " << x1 + << "," << y1 << " to " << x << "x" << y; + return s.str(); +} +SVGCommandType SVGCubicCurveTo::getType() +{ + return absolute ? SVG_CUBIC_CURVE_TO_ABS : SVG_CUBIC_CURVE_TO_REL; +} + +SVGSmoothCubicCurveTo::SVGSmoothCubicCurveTo(double _x1, double _y1, double x, double y, bool abs) + : SVGCommand(x, y, abs), x1(_x1), y1(_y1) +{ +} + +const string SVGSmoothCubicCurveTo::toString() const +{ + stringstream s; + s << (absolute ? "S" : "s") << x1 << "," << y1 << " " << x << "," << y; + return s.str(); +} +string SVGSmoothCubicCurveTo::toString2() +{ + stringstream s; + s << "Smooth cubic curve to (" << (absolute ? "absolute" : "relative") << ") control point: " << x1 << "," << y1 + << " to " << x << "x" << y; + return s.str(); +} +SVGCommandType SVGSmoothCubicCurveTo::getType() +{ + return absolute ? SVG_SMOOTH_CUBIC_CURVE_TO_ABS : SVG_SMOOTH_CUBIC_CURVE_TO_REL; +} + +SVGQuadraticCurveTo::SVGQuadraticCurveTo(double _x0, double _y0, double x, double y, bool abs) + : SVGCommand(x, y, abs), x0(_x0), y0(_y0) +{ +} +const string SVGQuadraticCurveTo::toString() const +{ + stringstream s; + s << (absolute ? "Q" : "q") << x0 << "," << y0 << " " << x << "," << y; + return s.str(); +} +string SVGQuadraticCurveTo::toString2() +{ + stringstream s; + s << "quadratic curve (" << (absolute ? "absolute" : "relative") << ") control point: " << x0 << "," << y0 << " to " + << x << "x" << y; + return s.str(); +} +SVGCommandType SVGQuadraticCurveTo::getType() +{ + return absolute ? SVG_QUADRATIC_CURVE_TO_ABS : SVG_QUADRATIC_CURVE_TO_REL; +} +SVGSmoothQuadraticCurveTo::SVGSmoothQuadraticCurveTo(double x, double y, bool abs) : SVGCommand(x, y, abs) +{ +} +const string SVGSmoothQuadraticCurveTo::toString() const +{ + stringstream s; + s << (absolute ? "T" : "t") << x << "," << y; + return s.str(); +} +string SVGSmoothQuadraticCurveTo::toString2() +{ + stringstream s; + s << "Smooth quadratic curve (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y; + return s.str(); +} +SVGCommandType SVGSmoothQuadraticCurveTo::getType() +{ + return absolute ? SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS : SVG_SMOOTH_QUADRATIC_CURVE_TO_REL; +} + +SVGArcTo::SVGArcTo(double rx, double ry, double rotxaxis, bool large, bool sweep, double x, double y, bool abs) + : SVGCommand(x, y, abs) +{ + this->rx = rx; + this->ry = ry; + + this->rot = rotxaxis; + + this->large = large; + this->sweep = sweep; +} +const string SVGArcTo::toString() const +{ + stringstream s; + s << (absolute ? "A" : "a") << rx << "," << ry << " " << rot << " " << large << "," << sweep << " " << x << "," + << y; + return s.str(); +} + +string SVGArcTo::toString2() +{ + stringstream s; + s << "Arc (" << (absolute ? "absolute" : "relative") << "x-radii: " << rx << " y-radii: " << ry + << " x-rotation: " << rot << " large-arc: " << large << " sweep: " << sweep << " to: " << x << "x" << y; + return s.str(); +} + +SVGCommandType SVGArcTo::getType() +{ + return absolute ? SVG_ARC_TO_ABS : SVG_ARC_TO_REL; +} + +SVGClosePath::SVGClosePath(bool abs) : SVGCommand(0, 0, abs) +{ +} + +const string SVGClosePath::toString() const +{ + stringstream s; + s << (absolute ? "Z" : "z"); + return s.str(); +} +string SVGClosePath::toString2() +{ + stringstream s; + s << "Close path"; + return s.str(); +} +SVGCommandType SVGClosePath::getType() +{ + return SVG_CLOSE_PATH; +} +std::ostream &operator<<(std::ostream &out, const SVGParser::SVGPath &path) +{ + for (SVGParser::SVGPath::const_iterator it = path.begin(); it != path.end(); it++) + { + out << (*it)->toString(); + } + return out; +} +std::ostream &operator<<(std::ostream &out, const SVGParser::SVGCommand *cmd) +{ + out << cmd->toString(); + return out; +} + +}; // namespace SVGParser + +SvgParser::SvgParser(const std::string path, double width, double height) : path(path), width(width), height(height) { } Point SvgParser::convertPoint(double x, double y) { - return Point{ x / width * 2. - 1. , 1. - y / height * 2. }; + return Point{x / width * 2. - 1., 1. - y / height * 2.}; } Point SvgParser::clampPoint(Point p) { - return Point{ std::clamp(p.x, -1., 1.) , std::clamp(p.y , -1., 1.) }; + return Point{std::clamp(p.x, -1., 1.), std::clamp(p.y, -1., 1.)}; } Point SvgParser::convertAbsPoint(double x, double y) { - return clampPoint(convertPoint(x, y)); + return clampPoint(convertPoint(x, y)); } Point SvgParser::convertRelPoint(Point pointBegin, double x, double y) { - return clampPoint(pointBegin + Point{ x / width * 2. , - y / height * 2. }); + return clampPoint(pointBegin + Point{x / width * 2., -y / height * 2.}); } using namespace SVGParser; vector> SvgParser::parse() { - vector line; - vector> lines; + vector line; + vector> lines; - istringstream stringStream(path); - SVGPath svgPath = parsePath(stringStream); - for (shared_ptr svgCmd : svgPath) - { - switch (svgCmd->getType()) - { - case SVG_MOVE_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertAbsPoint(cmd->x, cmd->y)); - break; - } - case SVG_LINE_TO_REL: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertRelPoint(line.back(), cmd->x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_LINE_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertAbsPoint(cmd->x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_HORIZONTAL_LINE_TO_REL: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertRelPoint(line.back(), cmd->x, 0)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_HORIZONTAL_LINE_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertAbsPoint(cmd->x, line.back().y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_VERTICAL_LINE_TO_REL: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertRelPoint(line.back(), 0, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_VERTICAL_LINE_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertAbsPoint(line.back().x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_QUADRATIC_CURVE_TO_REL: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - Point pointBegin = line.back(); - Point pointControl = convertRelPoint(pointBegin, cmd->x0, cmd->y0); - Point pointEnd = convertRelPoint(pointBegin, cmd->x, cmd->y); - line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.)); - line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.)); - line.push_back(pointEnd); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_QUADRATIC_CURVE_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - Point pointBegin = line.back(); - Point pointControl = convertAbsPoint(cmd->x0, cmd->y0); - Point pointEnd = convertAbsPoint(cmd->x, cmd->y); - line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.)); - line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.)); - line.push_back(pointEnd); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_CUBIC_CURVE_TO_REL: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - Point pointBegin = line.back(); - line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0)); - line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1)); - line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_CUBIC_CURVE_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertAbsPoint(cmd->x0, cmd->y0)); - line.push_back(convertAbsPoint(cmd->x1, cmd->y1)); - line.push_back(convertAbsPoint(cmd->x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - /*case SVG_ARC_TO_REL: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - Point pointBegin = line.back(); - line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0)); - line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1)); - line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - } - case SVG_ARC_TO_ABS: - { - shared_ptr cmd = static_pointer_cast(svgCmd); - line.push_back(convertAbsPoint(cmd->x0, cmd->y0)); - line.push_back(convertAbsPoint(cmd->x1, cmd->y1)); - line.push_back(convertAbsPoint(cmd->x, cmd->y)); - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - break; - }*/ - case SVG_CLOSE_PATH: - { - line.push_back(lines[0][0]); - lines.push_back(line); - break; - } - default: - cout << "PARSE ERROR" << endl; - break; - } - } - return lines; + istringstream stringStream(path); + SVGPath svgPath = parsePath(stringStream); + for (shared_ptr svgCmd : svgPath) + { + switch (svgCmd->getType()) + { + case SVG_MOVE_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertAbsPoint(cmd->x, cmd->y)); + break; + } + case SVG_LINE_TO_REL: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertRelPoint(line.back(), cmd->x, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_LINE_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertAbsPoint(cmd->x, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_HORIZONTAL_LINE_TO_REL: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertRelPoint(line.back(), cmd->x, 0)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_HORIZONTAL_LINE_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertAbsPoint(cmd->x, line.back().y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_VERTICAL_LINE_TO_REL: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertRelPoint(line.back(), 0, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_VERTICAL_LINE_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertAbsPoint(line.back().x, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_QUADRATIC_CURVE_TO_REL: { + shared_ptr cmd = static_pointer_cast(svgCmd); + Point pointBegin = line.back(); + Point pointControl = convertRelPoint(pointBegin, cmd->x0, cmd->y0); + Point pointEnd = convertRelPoint(pointBegin, cmd->x, cmd->y); + line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.)); + line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.)); + line.push_back(pointEnd); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_QUADRATIC_CURVE_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + Point pointBegin = line.back(); + Point pointControl = convertAbsPoint(cmd->x0, cmd->y0); + Point pointEnd = convertAbsPoint(cmd->x, cmd->y); + line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.)); + line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.)); + line.push_back(pointEnd); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_CUBIC_CURVE_TO_REL: { + shared_ptr cmd = static_pointer_cast(svgCmd); + Point pointBegin = line.back(); + line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0)); + line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1)); + line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + case SVG_CUBIC_CURVE_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + line.push_back(convertAbsPoint(cmd->x0, cmd->y0)); + line.push_back(convertAbsPoint(cmd->x1, cmd->y1)); + line.push_back(convertAbsPoint(cmd->x, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + } + /*case SVG_ARC_TO_REL: + { + shared_ptr cmd = static_pointer_cast(svgCmd); + Point pointBegin = line.back(); + line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0)); + line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1)); + line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y)); + lines.push_back(line); + line.erase(line.begin(), line.end() - 1); + break; + }*/ + case SVG_ARC_TO_ABS: { + shared_ptr cmd = static_pointer_cast(svgCmd); + ellipticalArcConverter(line.back(), cmd->rx, cmd->ry, cmd->rot, cmd->large, cmd->sweep, + convertAbsPoint(cmd->x, cmd->y), lines); + break; + } + case SVG_CLOSE_PATH: { + line.push_back(lines[0][0]); + lines.push_back(line); + break; + } + default: + cout << "PARSE ERROR" << endl; + break; + } + } + return lines; +} +void SvgParser::ellipticalArcConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA, + bool flagS, Point endPoint, vector> &lines) +{ + auto &start = beginPoint; + auto &end = endPoint; + if (fabs(start.x - end.x) < eps && fabs(start.y - end.y) < eps) + return; + if (fabs(radiusX) < eps || fabs(radiusY) < eps) + { + lines.emplace_back(vector{start, end}); + return; + } + radiusX = fabs(radiusX); + radiusY = fabs(radiusY); + auto center = centerConverter(start, radiusX, radiusY, phi, flagA, flagS, end); + Point r{center[0], center[1]}; + Point c{center[2], center[3]}; + double theta_1 = center[4]; + double deltTheta = center[5]; + double segments = deltTheta * 4.0 / PI; + int n = floor(segments); + Point p_1 = eConverter(c, r, cos(phi), sin(phi), theta_1); + Point e_1_ = e2Converter(c, r, cos(phi), sin(phi), theta_1); + double alpha = 0.26511477349130245; + double t = theta_1 + PI / 4.0; + for (int i = 1; i <= n; i++) + { + Point p_2 = eConverter(c, r, cos(phi), sin(phi), t); + Point e_2_ = e2Converter(c, r, cos(phi), sin(phi), t); + Point q_1 = p_1 + e_1_ * alpha; + Point q_2 = p_2 - e_2_ * alpha; + lines.emplace_back(vector{p_1, q_1, q_2, p_2}); + p_1 = p_2; + e_1_ = e_2_; + t = t + PI / 4.0; + } + if (n != ceil(segments)) { + double step = t - PI / 4.0; + double t = theta_1 + deltTheta; + double alpha_t = tan(step / 2.0); + alpha = sin(step) * (sqrt(4 + 3.0 * alpha_t * alpha_t) - 1.0) / 3.0; + Point p_2 = eConverter(c, r, cos(phi), sin(phi), t); + Point e_2_ = e2Converter(c, r, cos(phi), sin(phi), t); + Point q_1 = p_1 + e_1_ * alpha; + Point q_2 = p_2 - e_2_ * alpha; + lines.emplace_back(vector{p_1, q_1, q_2, p_2}); + } +} +vector SvgParser::centerConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA, + bool flagS, Point endPoint) +{ + Point r{radiusX, radiusY}; + double x_half = (beginPoint.x - endPoint.x) / 2.0; + double y_half = (beginPoint.y - endPoint.y) / 2.0; + Point r_2{radiusX * radiusX, radiusY * radiusY}; + double x_1 = x_half * cos(phi) + y_half * sin(phi); + double x_12 = x_1 * x_1; + double y_1 = y_half * cos(phi) + x_half * sin(phi); + double y_12 = y_1 * y_1; + double c_r = x_12 / r_2.x + y_12 / r_2.y; + if (fabs(c_r - 1.0) > eps) + { + c_r = sqrt(c_r); + r = Point{r.x * c_r, r.y * c_r}; + r_2 = Point{r.x * r.x, r.y * r.y}; + } + double d_q = r_2.x * y_12 + r_2.y * x_12; + double p_q = (r_2.x * r_2.y - d_q) / d_q; + double s_c = sqrt(max(0.0, p_q)); + if (flagA == flagS) + { + s_c *= -1.0; + } + Point c{r.x * s_c * y_1 / r.y, -r.y * s_c * x_1 / r.x}; + double c_x = c.x * cos(phi) - c.y * sin(phi) + (beginPoint.x + endPoint.x) / 2.0; + double c_y = c.x * sin(phi) + c.y * cos(phi) + (beginPoint.y + endPoint.y) / 2.0; + Point v{(x_1 - c.x) / r.x, (y_1 - c.y) / r.y}; + double theta_1 = angleConverter(Point{1, 0}, v); + double deltTheta = angleConverter(v, Point{(-x_1 - c.x) / r.x, (-y_1 - c.y) / r.y}); + while (deltTheta - 2.0 * PI < eps) + deltTheta += 2.0 * PI; + while (deltTheta - 2.0 * PI >= eps) + deltTheta -= 2.0 * PI; + if (!flagS) + { + deltTheta -= 2.0 * PI; + } + return vector{r.x, r.y, c_x, c_y, theta_1, deltTheta}; +} +double SvgParser::angleConverter(Point u, Point v) +{ + double n_u = sqrt(u.x * u.x + u.y * u.y); + double n_v = sqrt(v.x * v.x + v.y * v.y); + double a_c = (u.x * v.x + u.y * v.y) / n_u / n_v; + if (a_c - 1.0 > eps) + a_c = 1.0; + else if (a_c + 1.0 < eps) + a_c = -1.0; + a_c = acos(a_c); + if (u.x * v.y < u.y * v.x) + a_c = -a_c; + return a_c; +} +Point SvgParser::eConverter(Point c, Point r, double cosPhi, double sinPhi, double t) +{ + double a = r.x * cos(t); + double b = r.y * sin(t); + return Point{c.x + a * cosPhi - b * sinPhi, c.y + a * sinPhi - b * cosPhi}; +} +Point SvgParser::e2Converter(Point c, Point r, double cosPhi, double sinPhi, double t) +{ + double a = -r.x * cos(t); + double b = r.y * sin(t); + return Point{a * cosPhi - b * sinPhi, a * sinPhi - b * cosPhi}; } - diff --git a/ArchitectureColoredPainting/SvgParser.h b/ArchitectureColoredPainting/SvgParser.h index 0f6e4e6..3712027 100644 --- a/ArchitectureColoredPainting/SvgParser.h +++ b/ArchitectureColoredPainting/SvgParser.h @@ -1,140 +1,173 @@ #pragma once -#include #include "Line.h" -namespace SVGParser { - enum SVGCommandType { - SVG_INVALID = -1, - //SVG_MOVE_TO_REL, SVG_LINE_TO_REL, SVG_QUADRATIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_REL, - //SVG_MOVE_TO_ABS, SVG_LINE_TO_ABS, SVG_QUADRATIC_CURVE_TO_ABS, SVG_CUBIC_CURVE_TO_ABS, - SVG_MOVE_TO_REL, SVG_MOVE_TO_ABS, - SVG_LINE_TO_REL, SVG_LINE_TO_ABS, - SVG_HORIZONTAL_LINE_TO_REL, SVG_HORIZONTAL_LINE_TO_ABS, - SVG_VERTICAL_LINE_TO_REL, SVG_VERTICAL_LINE_TO_ABS, - SVG_QUADRATIC_CURVE_TO_REL, SVG_QUADRATIC_CURVE_TO_ABS, - SVG_CUBIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_ABS, - SVG_SMOOTH_CUBIC_CURVE_TO_REL, SVG_SMOOTH_CUBIC_CURVE_TO_ABS, - SVG_SMOOTH_QUADRATIC_CURVE_TO_REL, SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS, - SVG_ARC_TO_REL, SVG_ARC_TO_ABS, +#include +#include +using namespace std; +namespace SVGParser +{ +enum SVGCommandType +{ + SVG_INVALID = -1, + // SVG_MOVE_TO_REL, SVG_LINE_TO_REL, SVG_QUADRATIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_REL, + // SVG_MOVE_TO_ABS, SVG_LINE_TO_ABS, SVG_QUADRATIC_CURVE_TO_ABS, SVG_CUBIC_CURVE_TO_ABS, + SVG_MOVE_TO_REL, + SVG_MOVE_TO_ABS, + SVG_LINE_TO_REL, + SVG_LINE_TO_ABS, + SVG_HORIZONTAL_LINE_TO_REL, + SVG_HORIZONTAL_LINE_TO_ABS, + SVG_VERTICAL_LINE_TO_REL, + SVG_VERTICAL_LINE_TO_ABS, + SVG_QUADRATIC_CURVE_TO_REL, + SVG_QUADRATIC_CURVE_TO_ABS, + SVG_CUBIC_CURVE_TO_REL, + SVG_CUBIC_CURVE_TO_ABS, + SVG_SMOOTH_CUBIC_CURVE_TO_REL, + SVG_SMOOTH_CUBIC_CURVE_TO_ABS, + SVG_SMOOTH_QUADRATIC_CURVE_TO_REL, + SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS, + SVG_ARC_TO_REL, + SVG_ARC_TO_ABS, - SVG_CLOSE_PATH - }; - - bool isAbsolute(SVGCommandType); - class SVGCommand { - public: - SVGCommand(double, double, bool = false); - static const int length; - double x, y; - bool absolute; - virtual const std::string toString() const = 0; - virtual SVGCommandType getType() = 0; - virtual std::string toString2() = 0; - }; - class SVGMoveTo : public SVGCommand { - public: - static const int length = 2; - SVGMoveTo(double, double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - - class SVGLineTo : public SVGCommand { - public: - static const int length = 2; - SVGLineTo(double, double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - class SVGHLineTo : public SVGCommand { - public: - static const int length = 1; - SVGHLineTo(double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - class SVGVLineTo : public SVGCommand { - public: - static const int length = 1; - SVGVLineTo(double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - - class SVGQuadraticCurveTo : public SVGCommand { - public: - SVGQuadraticCurveTo(double, double, double, double, bool = false); - double x0, y0; - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - - class SVGCubicCurveTo : public SVGCommand { - public: - double x0, y0, x1, y1; - SVGCubicCurveTo(double, double, double, double, double, double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - class SVGSmoothQuadraticCurveTo : public SVGCommand { - public: - SVGSmoothQuadraticCurveTo(double, double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - - class SVGSmoothCubicCurveTo : public SVGCommand { - public: - double x1, y1; - SVGSmoothCubicCurveTo(double, double, double, double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - - class SVGArcTo : public SVGCommand { - public: - double rx, ry, rot; - bool large, sweep; - SVGArcTo(double, double, double, bool, bool, double, double, bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - - class SVGClosePath : public SVGCommand { - public: - SVGClosePath(bool = false); - virtual const std::string toString() const; - virtual SVGCommandType getType(); - virtual std::string toString2(); - }; - typedef vector> SVGPath; - SVGPath parsePath(std::istream&); - - std::ostream& operator<< (std::ostream&, const SVGParser::SVGPath&); - std::ostream& operator<< (std::ostream&, const SVGParser::SVGCommand*); + SVG_CLOSE_PATH }; + +bool isAbsolute(SVGCommandType); +class SVGCommand +{ + public: + SVGCommand(double, double, bool = false); + static const int length; + double x, y; + bool absolute; + virtual const std::string toString() const = 0; + virtual SVGCommandType getType() = 0; + virtual std::string toString2() = 0; +}; +class SVGMoveTo : public SVGCommand +{ + public: + static const int length = 2; + SVGMoveTo(double, double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; + +class SVGLineTo : public SVGCommand +{ + public: + static const int length = 2; + SVGLineTo(double, double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; +class SVGHLineTo : public SVGCommand +{ + public: + static const int length = 1; + SVGHLineTo(double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; +class SVGVLineTo : public SVGCommand +{ + public: + static const int length = 1; + SVGVLineTo(double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; + +class SVGQuadraticCurveTo : public SVGCommand +{ + public: + SVGQuadraticCurveTo(double, double, double, double, bool = false); + double x0, y0; + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; + +class SVGCubicCurveTo : public SVGCommand +{ + public: + double x0, y0, x1, y1; + SVGCubicCurveTo(double, double, double, double, double, double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; +class SVGSmoothQuadraticCurveTo : public SVGCommand +{ + public: + SVGSmoothQuadraticCurveTo(double, double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; + +class SVGSmoothCubicCurveTo : public SVGCommand +{ + public: + double x1, y1; + SVGSmoothCubicCurveTo(double, double, double, double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; + +class SVGArcTo : public SVGCommand +{ + public: + double rx, ry, rot; + bool large, sweep; + SVGArcTo(double, double, double, bool, bool, double, double, bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; + +class SVGClosePath : public SVGCommand +{ + public: + SVGClosePath(bool = false); + virtual const std::string toString() const; + virtual SVGCommandType getType(); + virtual std::string toString2(); +}; +typedef vector> SVGPath; +SVGPath parsePath(std::istream &); + +std::ostream &operator<<(std::ostream &, const SVGParser::SVGPath &); +std::ostream &operator<<(std::ostream &, const SVGParser::SVGCommand *); +}; // namespace SVGParser class SvgParser { -public: - SvgParser(const std::string path, const double width, const double height) ; - vector> parse(); -private: - const std::string path; - const double width; - const double height; + public: + SvgParser(const std::string path, const double width, const double height); + vector> parse(); - Point convertPoint(double x, double y); - Point clampPoint(Point p); - Point convertAbsPoint(double x, double y); - Point convertRelPoint(Point pointBegin, double x, double y); + private: + static constexpr const double eps = 1e-6; + static constexpr const double PI = 3.14159265358979323846; + const std::string path; + const double width; + const double height; + + Point convertPoint(double x, double y); + Point clampPoint(Point p); + Point convertAbsPoint(double x, double y); + Point convertRelPoint(Point pointBegin, double x, double y); + void ellipticalArcConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA, + bool flagS, Point endPoint,vector>& lines); + vector centerConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA, bool flagS, + Point endPoint); + double angleConverter(Point u, Point v); + Point eConverter(Point c, Point r, double cosPhi, double sinPhi, double t); + Point e2Converter(Point c, Point r, double cosPhi, double sinPhi, double t); }; -