Parcourir la source

LibWeb: Support percentage values in SVG line element

Edwin Hoksberg il y a 1 an
Parent
commit
ac6126e263

+ 23 - 0
Tests/LibWeb/Layout/expected/svg/svg-line-with-percentage-values.txt

@@ -0,0 +1,23 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x408 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x392 children: inline
+      frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 784x392] baseline: 392
+      SVGSVGBox <svg> at (8,8) content-size 784x392 [SVG] children: inline
+        TextNode <#text>
+        SVGGeometryBox <line> at (6.046875,135.40625) content-size 787.921875x3.921875 children: not-inline
+        TextNode <#text>
+        SVGGeometryBox <line> at (6.046875,264.765625) content-size 787.921875x3.921875 children: not-inline
+        TextNode <#text>
+        SVGGeometryBox <line> at (264.765625,6.046875) content-size 3.921875x395.921875 children: not-inline
+        TextNode <#text>
+        SVGGeometryBox <line> at (523.484375,6.046875) content-size 3.921875x395.921875 children: not-inline
+        TextNode <#text>
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x408]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x392]
+      SVGSVGPaintable (SVGSVGBox<svg>) [8,8 784x392]
+        SVGPathPaintable (SVGGeometryBox<line>) [6.046875,135.40625 787.921875x3.921875]
+        SVGPathPaintable (SVGGeometryBox<line>) [6.046875,264.765625 787.921875x3.921875]
+        SVGPathPaintable (SVGGeometryBox<line>) [264.765625,6.046875 3.921875x395.921875]
+        SVGPathPaintable (SVGGeometryBox<line>) [523.484375,6.046875 3.921875x395.921875]

+ 12 - 0
Tests/LibWeb/Layout/input/svg/svg-line-with-percentage-values.html

@@ -0,0 +1,12 @@
+<!doctype html><style>
+line {
+    stroke: red;
+}
+</style>
+<svg viewbox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
+    <line x1="0" y1="33%" x2="100%" y2="33%"></line>
+    <line x1="0" y1="66%" x2="100%" y2="66%"></line>
+
+    <line x1="33%" y1="0" x2="33%" y2="100%"></line>
+    <line x1="66%" y1="0" x2="66%" y2="100%"></line>
+</svg>

+ 20 - 17
Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp

@@ -30,23 +30,26 @@ void SVGLineElement::attribute_changed(FlyString const& name, Optional<String> c
     SVGGeometryElement::attribute_changed(name, old_value, value);
 
     if (name == SVG::AttributeNames::x1) {
-        m_x1 = AttributeParser::parse_coordinate(value.value_or(String {}));
+        m_x1 = AttributeParser::parse_number_percentage(value.value_or(String {}));
     } else if (name == SVG::AttributeNames::y1) {
-        m_y1 = AttributeParser::parse_coordinate(value.value_or(String {}));
+        m_y1 = AttributeParser::parse_number_percentage(value.value_or(String {}));
     } else if (name == SVG::AttributeNames::x2) {
-        m_x2 = AttributeParser::parse_coordinate(value.value_or(String {}));
+        m_x2 = AttributeParser::parse_number_percentage(value.value_or(String {}));
     } else if (name == SVG::AttributeNames::y2) {
-        m_y2 = AttributeParser::parse_coordinate(value.value_or(String {}));
+        m_y2 = AttributeParser::parse_number_percentage(value.value_or(String {}));
     }
 }
 
-Gfx::Path SVGLineElement::get_path(CSSPixelSize)
+Gfx::Path SVGLineElement::get_path(CSSPixelSize viewport_size)
 {
+    auto const viewport_width = viewport_size.width().to_float();
+    auto const viewport_height = viewport_size.height().to_float();
+
     Gfx::Path path;
-    float x1 = m_x1.value_or(0);
-    float y1 = m_y1.value_or(0);
-    float x2 = m_x2.value_or(0);
-    float y2 = m_y2.value_or(0);
+    float const x1 = m_x1.value_or({ 0, false }).resolve_relative_to(viewport_width);
+    float const y1 = m_y1.value_or({ 0, false }).resolve_relative_to(viewport_height);
+    float const x2 = m_x2.value_or({ 0, false }).resolve_relative_to(viewport_width);
+    float const y2 = m_y2.value_or({ 0, false }).resolve_relative_to(viewport_height);
 
     // 1. perform an absolute moveto operation to absolute location (x1,y1)
     path.move_to({ x1, y1 });
@@ -62,8 +65,8 @@ JS::NonnullGCPtr<SVGAnimatedLength> SVGLineElement::x1() const
 {
     // FIXME: Populate the unit type when it is parsed (0 here is "unknown").
     // FIXME: Create a proper animated value when animations are supported.
-    auto base_length = SVGLength::create(realm(), 0, m_x1.value_or(0));
-    auto anim_length = SVGLength::create(realm(), 0, m_x1.value_or(0));
+    auto base_length = SVGLength::create(realm(), 0, m_x1.value_or({ 0, false }).value());
+    auto anim_length = SVGLength::create(realm(), 0, m_x1.value_or({ 0, false }).value());
     return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length));
 }
 
@@ -72,8 +75,8 @@ JS::NonnullGCPtr<SVGAnimatedLength> SVGLineElement::y1() const
 {
     // FIXME: Populate the unit type when it is parsed (0 here is "unknown").
     // FIXME: Create a proper animated value when animations are supported.
-    auto base_length = SVGLength::create(realm(), 0, m_y1.value_or(0));
-    auto anim_length = SVGLength::create(realm(), 0, m_y1.value_or(0));
+    auto base_length = SVGLength::create(realm(), 0, m_y1.value_or({ 0, false }).value());
+    auto anim_length = SVGLength::create(realm(), 0, m_y1.value_or({ 0, false }).value());
     return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length));
 }
 
@@ -82,8 +85,8 @@ JS::NonnullGCPtr<SVGAnimatedLength> SVGLineElement::x2() const
 {
     // FIXME: Populate the unit type when it is parsed (0 here is "unknown").
     // FIXME: Create a proper animated value when animations are supported.
-    auto base_length = SVGLength::create(realm(), 0, m_x2.value_or(0));
-    auto anim_length = SVGLength::create(realm(), 0, m_x2.value_or(0));
+    auto base_length = SVGLength::create(realm(), 0, m_x2.value_or({ 0, false }).value());
+    auto anim_length = SVGLength::create(realm(), 0, m_x2.value_or({ 0, false }).value());
     return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length));
 }
 
@@ -92,8 +95,8 @@ JS::NonnullGCPtr<SVGAnimatedLength> SVGLineElement::y2() const
 {
     // FIXME: Populate the unit type when it is parsed (0 here is "unknown").
     // FIXME: Create a proper animated value when animations are supported.
-    auto base_length = SVGLength::create(realm(), 0, m_y2.value_or(0));
-    auto anim_length = SVGLength::create(realm(), 0, m_y2.value_or(0));
+    auto base_length = SVGLength::create(realm(), 0, m_y2.value_or({ 0, false }).value());
+    auto anim_length = SVGLength::create(realm(), 0, m_y2.value_or({ 0, false }).value());
     return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length));
 }
 

+ 4 - 4
Userland/Libraries/LibWeb/SVG/SVGLineElement.h

@@ -32,10 +32,10 @@ private:
 
     virtual void initialize(JS::Realm&) override;
 
-    Optional<float> m_x1;
-    Optional<float> m_y1;
-    Optional<float> m_x2;
-    Optional<float> m_y2;
+    Optional<NumberPercentage> m_x1;
+    Optional<NumberPercentage> m_y1;
+    Optional<NumberPercentage> m_x2;
+    Optional<NumberPercentage> m_y2;
 };
 
 }