diff --git a/Libraries/LibWeb/SVG/SVGRectElement.cpp b/Libraries/LibWeb/SVG/SVGRectElement.cpp index 1eed1e00eee..935d883b5dc 100644 --- a/Libraries/LibWeb/SVG/SVGRectElement.cpp +++ b/Libraries/LibWeb/SVG/SVGRectElement.cpp @@ -33,33 +33,33 @@ void SVGRectElement::attribute_changed(FlyString const& name, Optional c Base::attribute_changed(name, old_value, value, namespace_); if (name == SVG::AttributeNames::x) { - m_x = AttributeParser::parse_coordinate(value.value_or(String {})); + m_x = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::y) { - m_y = AttributeParser::parse_coordinate(value.value_or(String {})); + m_y = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::width) { - m_width = AttributeParser::parse_positive_length(value.value_or(String {})); + m_width = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::height) { - m_height = AttributeParser::parse_positive_length(value.value_or(String {})); + m_height = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::rx) { - m_radius_x = AttributeParser::parse_length(value.value_or(String {})); + m_radius_x = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::ry) { - m_radius_y = AttributeParser::parse_length(value.value_or(String {})); + m_radius_y = AttributeParser::parse_number_percentage(value.value_or(String {})); } } -Gfx::Path SVGRectElement::get_path(CSSPixelSize) +Gfx::Path SVGRectElement::get_path(CSSPixelSize viewport_size) { - float width = m_width.value_or(0); - float height = m_height.value_or(0); - float x = m_x.value_or(0); - float y = m_y.value_or(0); + float width = m_width.value_or(NumberPercentage::create_number(0)).resolve_relative_to(viewport_size.width().to_float()); + float height = m_height.value_or(NumberPercentage::create_number(0)).resolve_relative_to(viewport_size.height().to_float()); + float x = m_x.value_or(NumberPercentage::create_number(0)).resolve_relative_to(viewport_size.width().to_float()); + float y = m_y.value_or(NumberPercentage::create_number(0)).resolve_relative_to(viewport_size.height().to_float()); Gfx::Path path; // If width or height is zero, rendering is disabled. if (width == 0 || height == 0) return path; - auto corner_radii = calculate_used_corner_radius_values(); + auto corner_radii = calculate_used_corner_radius_values(viewport_size); float rx = corner_radii.width(); float ry = corner_radii.height(); @@ -112,7 +112,7 @@ Gfx::Path SVGRectElement::get_path(CSSPixelSize) return path; } -Gfx::FloatSize SVGRectElement::calculate_used_corner_radius_values() const +Gfx::FloatSize SVGRectElement::calculate_used_corner_radius_values(CSSPixelSize viewport_size) const { // 1. Let rx and ry be length values. float rx = 0; @@ -125,27 +125,27 @@ Gfx::FloatSize SVGRectElement::calculate_used_corner_radius_values() const } // 3. Otherwise, if a properly specified value is provided for ‘rx’, but not for ‘ry’, then set both rx and ry to the value of ‘rx’. else if (m_radius_x.has_value() && !m_radius_y.has_value()) { - rx = m_radius_x.value(); - ry = m_radius_x.value(); + rx = m_radius_x.value().resolve_relative_to(viewport_size.width().to_float()); + ry = m_radius_x.value().resolve_relative_to(viewport_size.width().to_float()); } // 4. Otherwise, if a properly specified value is provided for ‘ry’, but not for ‘rx’, then set both rx and ry to the value of ‘ry’. else if (m_radius_y.has_value() && !m_radius_x.has_value()) { - rx = m_radius_y.value(); - ry = m_radius_y.value(); + rx = m_radius_y.value().resolve_relative_to(viewport_size.height().to_float()); + ry = m_radius_y.value().resolve_relative_to(viewport_size.height().to_float()); } // 5. Otherwise, both ‘rx’ and ‘ry’ were specified properly. Set rx to the value of ‘rx’ and ry to the value of ‘ry’. else { - rx = m_radius_x.value(); - ry = m_radius_y.value(); + rx = m_radius_x.value().resolve_relative_to(viewport_size.width().to_float()); + ry = m_radius_y.value().resolve_relative_to(viewport_size.height().to_float()); } // 6. If rx is greater than half of ‘width’, then set rx to half of ‘width’. - auto half_width = m_width.value_or(0) / 2; + auto half_width = m_width.value_or(NumberPercentage::create_number(0)).resolve_relative_to(viewport_size.width().to_float()) / 2; if (rx > half_width) rx = half_width; // 7. If ry is greater than half of ‘height’, then set ry to half of ‘height’. - auto half_height = m_height.value_or(0) / 2; + auto half_height = m_height.value_or(NumberPercentage::create_number(0)).resolve_relative_to(viewport_size.height().to_float()) / 2; if (ry > half_height) ry = half_height; @@ -158,8 +158,8 @@ GC::Ref SVGRectElement::x() 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_x.value_or(0), SVGLength::ReadOnly::No); - auto anim_length = SVGLength::create(realm(), 0, m_x.value_or(0), SVGLength::ReadOnly::Yes); + auto base_length = SVGLength::create(realm(), 0, m_x.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::No); + auto anim_length = SVGLength::create(realm(), 0, m_x.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::Yes); return SVGAnimatedLength::create(realm(), base_length, anim_length); } @@ -168,8 +168,8 @@ GC::Ref SVGRectElement::y() 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_y.value_or(0), SVGLength::ReadOnly::No); - auto anim_length = SVGLength::create(realm(), 0, m_y.value_or(0), SVGLength::ReadOnly::Yes); + auto base_length = SVGLength::create(realm(), 0, m_y.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::No); + auto anim_length = SVGLength::create(realm(), 0, m_y.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::Yes); return SVGAnimatedLength::create(realm(), base_length, anim_length); } @@ -178,8 +178,8 @@ GC::Ref SVGRectElement::width() 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_width.value_or(0), SVGLength::ReadOnly::No); - auto anim_length = SVGLength::create(realm(), 0, m_width.value_or(0), SVGLength::ReadOnly::Yes); + auto base_length = SVGLength::create(realm(), 0, m_width.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::No); + auto anim_length = SVGLength::create(realm(), 0, m_width.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::Yes); return SVGAnimatedLength::create(realm(), base_length, anim_length); } @@ -188,8 +188,8 @@ GC::Ref SVGRectElement::height() 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_height.value_or(0), SVGLength::ReadOnly::No); - auto anim_length = SVGLength::create(realm(), 0, m_height.value_or(0), SVGLength::ReadOnly::Yes); + auto base_length = SVGLength::create(realm(), 0, m_height.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::No); + auto anim_length = SVGLength::create(realm(), 0, m_height.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::Yes); return SVGAnimatedLength::create(realm(), base_length, anim_length); } @@ -198,8 +198,8 @@ GC::Ref SVGRectElement::rx() 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_radius_x.value_or(0), SVGLength::ReadOnly::No); - auto anim_length = SVGLength::create(realm(), 0, m_radius_x.value_or(0), SVGLength::ReadOnly::Yes); + auto base_length = SVGLength::create(realm(), 0, m_radius_x.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::No); + auto anim_length = SVGLength::create(realm(), 0, m_radius_x.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::Yes); return SVGAnimatedLength::create(realm(), base_length, anim_length); } @@ -208,8 +208,8 @@ GC::Ref SVGRectElement::ry() 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_radius_y.value_or(0), SVGLength::ReadOnly::No); - auto anim_length = SVGLength::create(realm(), 0, m_radius_y.value_or(0), SVGLength::ReadOnly::Yes); + auto base_length = SVGLength::create(realm(), 0, m_radius_y.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::No); + auto anim_length = SVGLength::create(realm(), 0, m_radius_y.value_or(NumberPercentage::create_number(0)).value(), SVGLength::ReadOnly::Yes); return SVGAnimatedLength::create(realm(), base_length, anim_length); } diff --git a/Libraries/LibWeb/SVG/SVGRectElement.h b/Libraries/LibWeb/SVG/SVGRectElement.h index f647cd09ccd..2d1fa28c5b4 100644 --- a/Libraries/LibWeb/SVG/SVGRectElement.h +++ b/Libraries/LibWeb/SVG/SVGRectElement.h @@ -34,14 +34,14 @@ private: virtual void initialize(JS::Realm&) override; - Gfx::FloatSize calculate_used_corner_radius_values() const; + Gfx::FloatSize calculate_used_corner_radius_values(CSSPixelSize viewport_size) const; - Optional m_x; - Optional m_y; - Optional m_width; - Optional m_height; - Optional m_radius_x; - Optional m_radius_y; + Optional m_x; + Optional m_y; + Optional m_width; + Optional m_height; + Optional m_radius_x; + Optional m_radius_y; }; } diff --git a/Tests/LibWeb/Layout/expected/svg/rect-percentages.txt b/Tests/LibWeb/Layout/expected/svg/rect-percentages.txt new file mode 100644 index 00000000000..3d7e1cb7b37 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/svg/rect-percentages.txt @@ -0,0 +1,16 @@ +Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not-inline + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 216 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 200 0+0+8] children: inline + frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 300x200] baseline: 200 + SVGSVGBox at [8,8] [0+0+0 300 0+0+0] [0+0+0 200 0+0+0] [SVG] children: not-inline + SVGGeometryBox at [83,108] [0+0+0 99 0+0+0] [0+0+0 99 0+0+0] children: not-inline + TextNode <#text> (not painted) + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x216] + PaintableWithLines (BlockContainer) [8,8 784x200] + SVGSVGPaintable (SVGSVGBox) [8,8 300x200] + SVGPathPaintable (SVGGeometryBox) [83,108 99x99] + +SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) + SC for BlockContainer [0,0 800x216] [children: 0] (z-index: auto) diff --git a/Tests/LibWeb/Layout/input/svg/rect-percentages.html b/Tests/LibWeb/Layout/input/svg/rect-percentages.html new file mode 100644 index 00000000000..1a0369eacbf --- /dev/null +++ b/Tests/LibWeb/Layout/input/svg/rect-percentages.html @@ -0,0 +1 @@ + diff --git a/Tests/LibWeb/Screenshot/images/svg-maskContentUnits-ref.png b/Tests/LibWeb/Screenshot/images/svg-maskContentUnits-ref.png index 6e21e12b69a..9f5fcc8c93d 100644 Binary files a/Tests/LibWeb/Screenshot/images/svg-maskContentUnits-ref.png and b/Tests/LibWeb/Screenshot/images/svg-maskContentUnits-ref.png differ diff --git a/Tests/LibWeb/Screenshot/input/svg-maskContentUnits.html b/Tests/LibWeb/Screenshot/input/svg-maskContentUnits.html index d23a8431e18..1a8d717f951 100644 --- a/Tests/LibWeb/Screenshot/input/svg-maskContentUnits.html +++ b/Tests/LibWeb/Screenshot/input/svg-maskContentUnits.html @@ -1,5 +1,5 @@ - +