Browse Source

LibWeb: Expose SVG length/coordinate parsing methods

This is all still quite ad-hoc. Eventually these will both need to
support units (like with CSS Lengths) but for now we can continue only
using numbers.
Sam Atkins 3 năm trước cách đây
mục cha
commit
9424c67ed5

+ 51 - 1
Userland/Libraries/LibWeb/SVG/AttributeParser.cpp

@@ -26,6 +26,44 @@ Vector<PathInstruction> AttributeParser::parse_path_data()
     return m_instructions;
 }
 
+Optional<float> 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<float> 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<float> 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<float> AttributeParser::parse_coordinate_pair()
 {
     Vector<float> 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() == '.');
 }

+ 6 - 0
Userland/Libraries/LibWeb/SVG/AttributeParser.h

@@ -39,6 +39,10 @@ public:
 
     Vector<PathInstruction> parse_path_data();
 
+    static Optional<float> parse_coordinate(StringView input);
+    static Optional<float> parse_length(StringView input);
+    static Optional<float> 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<float> parse_coordinate_pair();
     Vector<float> 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(); }