MCPcopy Create free account
hub / github.com/dalboris/vpaint / parsePathData

Function parsePathData

src/Gui/SvgParser.cpp:718–853  ·  view source on GitHub ↗

Parses the given path data string `d` into a sequence of SvgPathCommands, according to the SVG 1.1 grammar: https://www.w3.org/TR/SVG11/paths.html#PathDataBNF In case of invalid syntax, an error string is written to the optional output parameter `error`, and the returned SvgPathCommands is the path data up to (but not including) the first command segment with an invalid syntax, as per the SVG re

Source from the content-addressed store, hash-verified

716// user.
717//
718std::vector<SvgPathCommand> parsePathData(
719 const std::string& d, std::string* error = nullptr)
720{
721 using t = SvgPathCommandType;
722 using a = SvgPathArgumentType;
723 auto it = d.cbegin();
724 auto end = d.cend();
725 std::vector<SvgPathCommand> cmds;
726 readWhitespaces(it, end);
727 while (it != end) {
728
729 // Read command type and relativeness
730 SvgPathCommandType type;
731 bool relative;
732 switch(*it) {
733 case 'Z': type = t::ClosePath; relative = false; break;
734 case 'M': type = t::MoveTo; relative = false; break;
735 case 'L': type = t::LineTo; relative = false; break;
736 case 'H': type = t::HLineTo; relative = false; break;
737 case 'V': type = t::VLineTo; relative = false; break;
738 case 'C': type = t::CCurveTo; relative = false; break;
739 case 'S': type = t::SCurveTo; relative = false; break;
740 case 'Q': type = t::QCurveTo; relative = false; break;
741 case 'T': type = t::TCurveTo; relative = false; break;
742 case 'A': type = t::ArcTo; relative = false; break;
743
744 case 'z': type = t::ClosePath; relative = true; break;
745 case 'm': type = t::MoveTo; relative = true; break;
746 case 'l': type = t::LineTo; relative = true; break;
747 case 'h': type = t::HLineTo; relative = true; break;
748 case 'v': type = t::VLineTo; relative = true; break;
749 case 'c': type = t::CCurveTo; relative = true; break;
750 case 's': type = t::SCurveTo; relative = true; break;
751 case 'q': type = t::QCurveTo; relative = true; break;
752 case 't': type = t::TCurveTo; relative = true; break;
753 case 'a': type = t::ArcTo; relative = true; break;
754
755 default:
756 // Unknown command character, or failed to parse first arg
757 // of non-first argtuple of previous command.
758 if (error) {
759 *error = "Failed to read command type or argument: ";
760 *error += *it;
761 }
762 return cmds;
763 }
764
765 // Ensure first command is a MoveTo
766 if (cmds.empty() && type != t::MoveTo) {
767 if (error) {
768 *error = "First command must be 'M' or 'm'. Found '";
769 *error += *it;
770 *error += "' instead.";
771 }
772 return cmds;
773 }
774
775 // Advance iterator on success

Callers 1

readPathFunction · 0.85

Calls 11

readWhitespacesFunction · 0.85
readCommaWhitespacesFunction · 0.85
readNumberFunction · 0.85
readUnsignedFunction · 0.85
readFlagFunction · 0.85
SvgPathCommandClass · 0.85
reserveMethod · 0.80
cbeginMethod · 0.45
cendMethod · 0.45
sizeMethod · 0.45
push_backMethod · 0.45

Tested by

no test coverage detected