diff --git a/Libraries/LibWeb/SVG/SVGElement.cpp b/Libraries/LibWeb/SVG/SVGElement.cpp index 7e9aa1d5622..b5b7b1224d5 100644 --- a/Libraries/LibWeb/SVG/SVGElement.cpp +++ b/Libraries/LibWeb/SVG/SVGElement.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace Web::SVG { @@ -32,75 +33,92 @@ void SVGElement::initialize(JS::Realm& realm) } struct NamedPropertyID { - NamedPropertyID(CSS::PropertyID property_id) + NamedPropertyID(CSS::PropertyID property_id, Vector supported_elements = {}) : id(property_id) , name(CSS::string_from_property_id(property_id)) + , supported_elements(move(supported_elements)) { } CSS::PropertyID id; - StringView name; + FlyString name; + Vector supported_elements; }; -static Array const attribute_style_properties { - // FIXME: The `fill` attribute and CSS `fill` property are not the same! But our support is limited enough that they are equivalent for now. - NamedPropertyID(CSS::PropertyID::Fill), - // FIXME: The `stroke` attribute and CSS `stroke` property are not the same! But our support is limited enough that they are equivalent for now. - NamedPropertyID(CSS::PropertyID::ClipPath), - NamedPropertyID(CSS::PropertyID::ClipRule), - NamedPropertyID(CSS::PropertyID::Color), - NamedPropertyID(CSS::PropertyID::Cursor), - NamedPropertyID(CSS::PropertyID::Direction), - NamedPropertyID(CSS::PropertyID::Display), - NamedPropertyID(CSS::PropertyID::FillOpacity), - NamedPropertyID(CSS::PropertyID::FillRule), - NamedPropertyID(CSS::PropertyID::FontFamily), - NamedPropertyID(CSS::PropertyID::FontSize), - NamedPropertyID(CSS::PropertyID::FontStyle), - NamedPropertyID(CSS::PropertyID::FontWeight), - NamedPropertyID(CSS::PropertyID::ImageRendering), - NamedPropertyID(CSS::PropertyID::LetterSpacing), - NamedPropertyID(CSS::PropertyID::Mask), - NamedPropertyID(CSS::PropertyID::MaskType), - NamedPropertyID(CSS::PropertyID::Opacity), - NamedPropertyID(CSS::PropertyID::Overflow), - NamedPropertyID(CSS::PropertyID::PointerEvents), - NamedPropertyID(CSS::PropertyID::StopColor), - NamedPropertyID(CSS::PropertyID::StopOpacity), - NamedPropertyID(CSS::PropertyID::Stroke), - NamedPropertyID(CSS::PropertyID::StrokeDasharray), - NamedPropertyID(CSS::PropertyID::StrokeDashoffset), - NamedPropertyID(CSS::PropertyID::StrokeLinecap), - NamedPropertyID(CSS::PropertyID::StrokeLinejoin), - NamedPropertyID(CSS::PropertyID::StrokeMiterlimit), - NamedPropertyID(CSS::PropertyID::StrokeOpacity), - NamedPropertyID(CSS::PropertyID::StrokeWidth), - NamedPropertyID(CSS::PropertyID::TextAnchor), - NamedPropertyID(CSS::PropertyID::TextRendering), - NamedPropertyID(CSS::PropertyID::TextOverflow), - NamedPropertyID(CSS::PropertyID::TransformOrigin), - NamedPropertyID(CSS::PropertyID::UnicodeBidi), - NamedPropertyID(CSS::PropertyID::Visibility), - NamedPropertyID(CSS::PropertyID::WhiteSpace), - NamedPropertyID(CSS::PropertyID::WordSpacing), - NamedPropertyID(CSS::PropertyID::WritingMode), -}; +static ReadonlySpan attribute_style_properties() +{ + static Array const properties = { + // FIXME: The `fill` attribute and CSS `fill` property are not the same! But our support is limited enough that they are equivalent for now. + NamedPropertyID(CSS::PropertyID::Fill), + // FIXME: The `stroke` attribute and CSS `stroke` property are not the same! But our support is limited enough that they are equivalent for now. + NamedPropertyID(CSS::PropertyID::ClipPath), + NamedPropertyID(CSS::PropertyID::ClipRule), + NamedPropertyID(CSS::PropertyID::Color), + NamedPropertyID(CSS::PropertyID::Cursor), + NamedPropertyID(CSS::PropertyID::Cx, { SVG::TagNames::circle, SVG::TagNames::ellipse }), + NamedPropertyID(CSS::PropertyID::Cy, { SVG::TagNames::circle, SVG::TagNames::ellipse }), + NamedPropertyID(CSS::PropertyID::Direction), + NamedPropertyID(CSS::PropertyID::Display), + NamedPropertyID(CSS::PropertyID::FillOpacity), + NamedPropertyID(CSS::PropertyID::FillRule), + NamedPropertyID(CSS::PropertyID::FontFamily), + NamedPropertyID(CSS::PropertyID::FontSize), + NamedPropertyID(CSS::PropertyID::FontStyle), + NamedPropertyID(CSS::PropertyID::FontWeight), + NamedPropertyID(CSS::PropertyID::Height, { SVG::TagNames::foreignObject, SVG::TagNames::image, SVG::TagNames::rect, SVG::TagNames::svg, SVG::TagNames::symbol, SVG::TagNames::use }), + NamedPropertyID(CSS::PropertyID::ImageRendering), + NamedPropertyID(CSS::PropertyID::LetterSpacing), + NamedPropertyID(CSS::PropertyID::Mask), + NamedPropertyID(CSS::PropertyID::MaskType), + NamedPropertyID(CSS::PropertyID::Opacity), + NamedPropertyID(CSS::PropertyID::Overflow), + NamedPropertyID(CSS::PropertyID::PointerEvents), + NamedPropertyID(CSS::PropertyID::R, { SVG::TagNames::circle }), + NamedPropertyID(CSS::PropertyID::Rx, { SVG::TagNames::ellipse, SVG::TagNames::rect }), + NamedPropertyID(CSS::PropertyID::Ry, { SVG::TagNames::ellipse, SVG::TagNames::rect }), + NamedPropertyID(CSS::PropertyID::StopColor), + NamedPropertyID(CSS::PropertyID::StopOpacity), + NamedPropertyID(CSS::PropertyID::Stroke), + NamedPropertyID(CSS::PropertyID::StrokeDasharray), + NamedPropertyID(CSS::PropertyID::StrokeDashoffset), + NamedPropertyID(CSS::PropertyID::StrokeLinecap), + NamedPropertyID(CSS::PropertyID::StrokeLinejoin), + NamedPropertyID(CSS::PropertyID::StrokeMiterlimit), + NamedPropertyID(CSS::PropertyID::StrokeOpacity), + NamedPropertyID(CSS::PropertyID::StrokeWidth), + NamedPropertyID(CSS::PropertyID::TextAnchor), + NamedPropertyID(CSS::PropertyID::TextRendering), + NamedPropertyID(CSS::PropertyID::TextOverflow), + NamedPropertyID(CSS::PropertyID::TransformOrigin), + NamedPropertyID(CSS::PropertyID::UnicodeBidi), + NamedPropertyID(CSS::PropertyID::Visibility), + NamedPropertyID(CSS::PropertyID::WhiteSpace), + NamedPropertyID(CSS::PropertyID::Width, { SVG::TagNames::foreignObject, SVG::TagNames::image, SVG::TagNames::rect, SVG::TagNames::svg, SVG::TagNames::symbol, SVG::TagNames::use }), + NamedPropertyID(CSS::PropertyID::WordSpacing), + NamedPropertyID(CSS::PropertyID::WritingMode), + NamedPropertyID(CSS::PropertyID::X, { SVG::TagNames::foreignObject, SVG::TagNames::image, SVG::TagNames::rect, SVG::TagNames::svg, SVG::TagNames::symbol, SVG::TagNames::use }), + NamedPropertyID(CSS::PropertyID::Y, { SVG::TagNames::foreignObject, SVG::TagNames::image, SVG::TagNames::rect, SVG::TagNames::svg, SVG::TagNames::symbol, SVG::TagNames::use }), + }; + return properties; +} bool SVGElement::is_presentational_hint(FlyString const& name) const { if (Base::is_presentational_hint(name)) return true; - return any_of(attribute_style_properties, [&](auto& property) { return name.equals_ignoring_ascii_case(property.name); }); + return any_of(attribute_style_properties(), [&](auto& property) { return name.equals_ignoring_ascii_case(property.name); }); } void SVGElement::apply_presentational_hints(GC::Ref cascaded_properties) const { CSS::Parser::ParsingParams parsing_context { document(), CSS::Parser::ParsingMode::SVGPresentationAttribute }; for_each_attribute([&](auto& name, auto& value) { - for (auto property : attribute_style_properties) { + for (auto& property : attribute_style_properties()) { if (!name.equals_ignoring_ascii_case(property.name)) continue; + if (!property.supported_elements.is_empty() && !property.supported_elements.contains_slow(local_name())) + continue; if (property.id == CSS::PropertyID::Mask) { // Mask is a shorthand property in CSS, but parse_css_value does not take that into account. For now, // just parse as 'mask-image' as anything else is currently not supported. diff --git a/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt b/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt index 572b24dfc6d..d65a1af20d5 100644 --- a/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt +++ b/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt @@ -3,7 +3,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline BlockContainer at (8,8) content-size 784x100 children: inline frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 100x100] baseline: 100 SVGSVGBox at (8,8) content-size 100x100 [SVG] children: inline - SVGForeignObjectBox at (8,8) content-size 0x0 children: not-inline + SVGForeignObjectBox at (8,8) content-size 100x100 children: not-inline BlockContainer
at (8,8) content-size 100x18 children: inline frag 0 from TextNode start: 0, length: 3, rect: [8,8 27.15625x18] baseline: 13.796875 "foo" @@ -13,6 +13,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x116] PaintableWithLines (BlockContainer) [8,8 784x100] SVGSVGPaintable (SVGSVGBox) [8,8 100x100] - SVGForeignObjectPaintable (SVGForeignObjectBox) [8,8 0x0] overflow: [8,8 100x18] + SVGForeignObjectPaintable (SVGForeignObjectBox) [8,8 100x100] PaintableWithLines (BlockContainer
) [8,8 100x18] TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-relevant.txt b/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-relevant.txt index 64f473ffefd..1737cbbb440 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-relevant.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-relevant.txt @@ -2,8 +2,8 @@ Harness status: OK Found 53 tests -42 Pass -11 Fail +48 Pass +5 Fail Pass clip-path presentation attribute supported on a relevant element Pass clip-rule presentation attribute supported on a relevant element Pass color presentation attribute supported on a relevant element @@ -22,7 +22,7 @@ Fail font-stretch presentation attribute supported on a relevant element Pass font-style presentation attribute supported on a relevant element Fail font-variant presentation attribute supported on a relevant element Pass font-weight presentation attribute supported on a relevant element -Fail height presentation attribute supported on a relevant element +Pass height presentation attribute supported on a relevant element Pass image-rendering presentation attribute supported on a relevant element Pass letter-spacing presentation attribute supported on a relevant element Pass mask-type presentation attribute supported on a relevant element @@ -31,8 +31,8 @@ Pass opacity presentation attribute supported on a relevant element Pass overflow presentation attribute supported on a relevant element Pass pointer-events presentation attribute supported on a relevant element Pass r presentation attribute supported on a relevant element -Fail rx presentation attribute supported on a relevant element -Fail ry presentation attribute supported on a relevant element +Pass rx presentation attribute supported on a relevant element +Pass ry presentation attribute supported on a relevant element Pass stop-color presentation attribute supported on a relevant element Pass stop-opacity presentation attribute supported on a relevant element Pass stroke presentation attribute supported on a relevant element @@ -52,8 +52,8 @@ Fail transform presentation attribute supported on a relevant element Pass unicode-bidi presentation attribute supported on a relevant element Pass visibility presentation attribute supported on a relevant element Pass white-space presentation attribute supported on a relevant element -Fail width presentation attribute supported on a relevant element +Pass width presentation attribute supported on a relevant element Pass word-spacing presentation attribute supported on a relevant element Pass writing-mode presentation attribute supported on a relevant element -Fail x presentation attribute supported on a relevant element -Fail y presentation attribute supported on a relevant element \ No newline at end of file +Pass x presentation attribute supported on a relevant element +Pass y presentation attribute supported on a relevant element \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-special-cases.txt b/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-special-cases.txt new file mode 100644 index 00000000000..c0ac13eff99 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/svg/styling/presentation-attributes-special-cases.txt @@ -0,0 +1,32 @@ +Harness status: OK + +Found 26 tests + +17 Pass +9 Fail +Pass cx and cy presentation attributes supported on circle element +Pass cx and cy presentation attributes supported on ellipse element +Pass x, y, width, and height presentation attributes supported on foreignObject element +Pass x, y, width, and height presentation attributes supported on image element +Pass x, y, width, and height presentation attributes supported on rect element +Pass x, y, width, and height presentation attributes supported on svg element +Pass x, y, width, and height presentation attributes supported on symbol element +Fail x, y, width, and height presentation attributes supported on use element +Pass r presentation attribute supported on circle element +Pass rx and ry presentation attributes supported on ellipse element +Pass rx and ry presentation attributes supported on rect element +Pass cx and cy presentation attributes not supported on other elements +Pass x, y, width, and height presentation attributes not supported on other elements +Pass r presentation attribute not supported on other elements +Pass rx and ry presentation attributes not supported on other elements +Fail fill presentation attribute not supported on animate +Fail fill presentation attribute not supported on animateMotion +Fail fill presentation attribute not supported on animateTransform +Fail fill presentation attribute not supported on set +Fail transform presentation attribute supported on g +Fail patternTransform presentation attribute supported on pattern +Fail gradientTransform presentation attribute supported on linearGradient +Fail gradientTransform presentation attribute supported on radialGradient +Pass transform presentation attribute not supported on pattern or gradient elements +Pass patternTransform presentation attribute not supported on g or gradient elements +Pass gradientTransform presentation attribute not supported on g or pattern elements \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/svg/styling/presentation-attributes-special-cases.html b/Tests/LibWeb/Text/input/wpt-import/svg/styling/presentation-attributes-special-cases.html new file mode 100644 index 00000000000..b398731cef5 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/svg/styling/presentation-attributes-special-cases.html @@ -0,0 +1,149 @@ + + +SVG presentation attributes - special cases + + + + + +