diff --git a/Tests/LibWeb/Layout/expected/svg/svg-symbol-with-viewbox.txt b/Tests/LibWeb/Layout/expected/svg/svg-symbol-with-viewbox.txt new file mode 100644 index 00000000000..8e783f2eb7d --- /dev/null +++ b/Tests/LibWeb/Layout/expected/svg/svg-symbol-with-viewbox.txt @@ -0,0 +1,20 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x150 children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline + TextNode <#text> + TextNode <#text> + BlockContainer
at (8,8) content-size 784x150 children: inline + line 0 width: 300, height: 150, bottom: 150, baseline: 150 + frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 300x150] + TextNode <#text> + SVGSVGBox at (8,8) content-size 300x150 [SVG] children: inline + TextNode <#text> + InlineNode + InlineNode + TextNode <#text> + SVGGeometryBox at (92.375,26.75) content-size 131.25x112.140625 children: inline + TextNode <#text> + TextNode <#text> + TextNode <#text> + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/svg/svg-symbol-with-viewbox.html b/Tests/LibWeb/Layout/input/svg/svg-symbol-with-viewbox.html new file mode 100644 index 00000000000..3c934502b93 --- /dev/null +++ b/Tests/LibWeb/Layout/input/svg/svg-symbol-with-viewbox.html @@ -0,0 +1,13 @@ + + + + + + + + +
+ + + diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index a7d3013f17f..b185dbb0ffe 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -159,7 +159,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available auto path_transform = dom_node.get_transform(); double viewbox_scale = 1; - auto maybe_view_box = svg_svg_element.view_box(); + auto maybe_view_box = dom_node.view_box(); if (maybe_view_box.has_value()) { // FIXME: This should allow just one of width or height to be specified. // E.g. We should be able to layout where height is unspecified/auto. diff --git a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp index 83744c80a80..ccf7caacd4a 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp @@ -33,7 +33,7 @@ Optional SVGGeometryBox::layout_transform() const double scaling = 1; auto origin = viewbox_origin().to_type().to_type(); Gfx::FloatPoint paint_offset = {}; - if (svg_box && svg_box->view_box().has_value()) { + if (svg_box && geometry_element.view_box().has_value()) { // Note: SVGFormattingContext has already done the scaling based on the viewbox, // we now have to derive what it was from the original bounding box size. // FIXME: It would be nice if we could store the transform from layout somewhere, so we don't have to solve for it here. diff --git a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp index 77bf7a1e637..5835e5ab983 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp @@ -76,7 +76,7 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const auto offset = context.floored_device_point(svg_element_rect.location()).to_type().to_type(); painter.translate(offset); - auto maybe_view_box = svg_element->view_box(); + auto maybe_view_box = geometry_element.view_box(); auto transform = layout_box().layout_transform(); if (!transform.has_value()) diff --git a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp index caae6eaf813..67835947610 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace Web::SVG { @@ -230,4 +231,19 @@ Optional SVGGraphicsElement::stroke_width() const return width.to_px(*layout_node(), scaled_viewport_size).to_double(); } +Optional SVGGraphicsElement::view_box() const +{ + if (auto* svg_svg_element = shadow_including_first_ancestor_of_type()) { + if (svg_svg_element->view_box().has_value()) + return svg_svg_element->view_box(); + } + + if (auto* svg_symbol_element = shadow_including_first_ancestor_of_type()) { + if (svg_symbol_element->view_box().has_value()) + return svg_symbol_element->view_box(); + } + + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h index 68931c938e9..060c05dc98b 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace Web::SVG { @@ -45,6 +46,8 @@ public: Optional fill_paint_style(SVGPaintContext const&) const; Optional stroke_paint_style(SVGPaintContext const&) const; + Optional view_box() const; + protected: SVGGraphicsElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp index 5306a248c57..10af9b646f3 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -44,8 +45,12 @@ void SVGSymbolElement::apply_presentational_hints(CSS::StyleProperties& style) c // and this declaration must have importance over any other CSS rule or presentation attribute. style.set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::None)).release_value_but_fixme_should_propagate_errors()); } +} - // TODO: Parse viewBox and apply it in SVGGraphicsElement/SVGGraphicsPaintable +void SVGSymbolElement::attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) +{ + if (name.equals_ignoring_ascii_case(SVG::AttributeNames::viewBox)) + m_view_box = try_parse_view_box(value); } bool SVGSymbolElement::is_direct_child_of_use_shadow_tree() const diff --git a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h index 3b571d43979..0c690a13aa8 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h @@ -18,12 +18,18 @@ public: void apply_presentational_hints(CSS::StyleProperties& style) const override; + Optional view_box() const { return m_view_box; } + private: SVGSymbolElement(DOM::Document&, DOM::QualifiedName); virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; bool is_direct_child_of_use_shadow_tree() const; + + virtual void attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) override; + + Optional m_view_box; }; }