diff --git a/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp b/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp index cc68f80345..e6eb4c5d9d 100644 --- a/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp +++ b/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp @@ -26,6 +26,44 @@ Vector AttributeParser::parse_path_data() return m_instructions; } +Optional AttributeParser::parse_coordinate(StringView input) +{ + AttributeParser parser { input }; + parser.parse_whitespace(); + if (parser.match_coordinate()) { + float result = parser.parse_coordinate(); + parser.parse_whitespace(); + if (parser.done()) + return result; + } + + return {}; +} + +Optional AttributeParser::parse_length(StringView input) +{ + AttributeParser parser { input }; + parser.parse_whitespace(); + if (parser.match_coordinate()) { + float result = parser.parse_length(); + parser.parse_whitespace(); + if (parser.done()) + return result; + } + + return {}; +} + +Optional AttributeParser::parse_positive_length(StringView input) +{ + // FIXME: Where this is used, the spec usually (always?) says "A negative value is an error (see Error processing)." + // So, implement error processing! Maybe this should return ErrorOr. + auto result = parse_length(input); + if (result.has_value() && result.value() < 0) + result.clear(); + return result; +} + void AttributeParser::parse_drawto() { if (match('M') || match('m')) { @@ -161,11 +199,18 @@ void AttributeParser::parse_elliptical_arc() } } -float AttributeParser::parse_coordinate() +float AttributeParser::parse_length() { return parse_sign() * parse_number(); } +float AttributeParser::parse_coordinate() +{ + // https://www.w3.org/TR/SVG11/types.html#DataTypeCoordinate + // coordinate ::= length + return parse_length(); +} + Vector AttributeParser::parse_coordinate_pair() { Vector coordinates; @@ -360,6 +405,11 @@ bool AttributeParser::match_comma_whitespace() const } bool AttributeParser::match_coordinate() const +{ + return match_length(); +} + +bool AttributeParser::match_length() const { return !done() && (isdigit(ch()) || ch() == '-' || ch() == '+' || ch() == '.'); } diff --git a/Userland/Libraries/LibWeb/SVG/AttributeParser.h b/Userland/Libraries/LibWeb/SVG/AttributeParser.h index 61a2ca690d..6564b6baa3 100644 --- a/Userland/Libraries/LibWeb/SVG/AttributeParser.h +++ b/Userland/Libraries/LibWeb/SVG/AttributeParser.h @@ -39,6 +39,10 @@ public: Vector parse_path_data(); + static Optional parse_coordinate(StringView input); + static Optional parse_length(StringView input); + static Optional parse_positive_length(StringView input); + private: void parse_drawto(); @@ -53,6 +57,7 @@ private: void parse_smooth_quadratic_bezier_curveto(); void parse_elliptical_arc(); + float parse_length(); float parse_coordinate(); Vector parse_coordinate_pair(); Vector parse_coordinate_sequence(); @@ -71,6 +76,7 @@ private: bool match_whitespace() const; bool match_comma_whitespace() const; bool match_coordinate() const; + bool match_length() const; bool match(char c) const { return !done() && ch() == c; } bool done() const { return m_cursor >= m_source.length(); }