Title: [290254] trunk/Source/WebCore
Revision
290254
Author
[email protected]
Date
2022-02-21 11:15:35 -0800 (Mon, 21 Feb 2022)

Log Message

[LBSE] Implement SVG2 rules to establish a stacking context
https://bugs.webkit.org/show_bug.cgi?id=236193

Reviewed by Rob Buis.

Follow the rules specified in https://www.w3.org/TR/SVG2/render.html#RenderingOrder,
when to create a stacking context. This is necessary to enforce layer creation.

Unlike SVG 1.1, SVG2 defines its whole rendering model, as well as painting operations
such as masking/clipping around the 'stacking-context' term that stems from CSS.
The definition is backwards compatible with SVG 1.1, except for un-spec'ed territory
missing from SVG 1.1, that's now specified for SVG2 (e.g. <foreignObject> + stacking context).

LBSE handles clipping / masking / etc. via RenderLayer, which is also responsbile for
for stacking-context managment. Therefore we need to follow the existing rules to enforce
a stacking context / RenderLayer creation in StyleAdjuster, by enforcing a non-auto 'used z-index'.

Covered by existing tests, no change in behaviour.

* style/StyleAdjuster.cpp:
(WebCore::Style::Adjuster::adjustSVGElementStyle):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (290253 => 290254)


--- trunk/Source/WebCore/ChangeLog	2022-02-21 18:57:52 UTC (rev 290253)
+++ trunk/Source/WebCore/ChangeLog	2022-02-21 19:15:35 UTC (rev 290254)
@@ -1,3 +1,27 @@
+2022-02-21  Nikolas Zimmermann  <[email protected]>
+
+        [LBSE] Implement SVG2 rules to establish a stacking context
+        https://bugs.webkit.org/show_bug.cgi?id=236193
+
+        Reviewed by Rob Buis.
+
+        Follow the rules specified in https://www.w3.org/TR/SVG2/render.html#RenderingOrder,
+        when to create a stacking context. This is necessary to enforce layer creation.
+
+        Unlike SVG 1.1, SVG2 defines its whole rendering model, as well as painting operations
+        such as masking/clipping around the 'stacking-context' term that stems from CSS.
+        The definition is backwards compatible with SVG 1.1, except for un-spec'ed territory
+        missing from SVG 1.1, that's now specified for SVG2 (e.g. <foreignObject> + stacking context).
+
+        LBSE handles clipping / masking / etc. via RenderLayer, which is also responsbile for
+        for stacking-context managment. Therefore we need to follow the existing rules to enforce
+        a stacking context / RenderLayer creation in StyleAdjuster, by enforcing a non-auto 'used z-index'.
+
+        Covered by existing tests, no change in behaviour.
+
+        * style/StyleAdjuster.cpp:
+        (WebCore::Style::Adjuster::adjustSVGElementStyle):
+
 2022-02-21  Myles C. Maxfield  <[email protected]>
 
         [WebGPU] Tracer bullet part 2: Fix infinite recursion in GPUDevice::ref()

Modified: trunk/Source/WebCore/style/StyleAdjuster.cpp (290253 => 290254)


--- trunk/Source/WebCore/style/StyleAdjuster.cpp	2022-02-21 18:57:52 UTC (rev 290253)
+++ trunk/Source/WebCore/style/StyleAdjuster.cpp	2022-02-21 19:15:35 UTC (rev 290254)
@@ -9,7 +9,7 @@
  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
  * Copyright (C) 2012, 2013 Google Inc. All rights reserved.
- * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2014, 2020, 2022 Igalia S.L.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -632,7 +632,45 @@
     if (!isPositioningAllowed)
         style.setPosition(RenderStyle::initialPosition());
 
-    // LegacyRenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    // SVG2: A new stacking context must be established at an SVG element for its descendants if:
+    // - it is the root element
+    // - the "z-index" property applies to the element and its computed value is an integer
+    // - the element is an outermost svg element, or a "foreignObject", "image", "marker", "mask", "pattern", "symbol" or "use" element
+    // - the element is an inner "svg" element and the computed value of its "overflow" property is a value other than visible
+    // - the element is subject to explicit clipping:
+    //   - the "clip" property applies to the element and it has a computed value other than auto
+    //   - the "clip-path" property applies to the element and it has a computed value other than none
+    // - the "mask" property applies to the element and it has a computed value other than none
+    // - the "filter" property applies to the element and it has a computed value other than none
+    // - a property defined in another specification is applied and that property is defined to establish a stacking context in SVG
+    //
+    // Some of the rules above were already enforced in StyleResolver::adjustRenderStyle() - for those cases assertions were added.
+    if (svgElement.document().settings().layerBasedSVGEngineEnabled() && style.hasAutoUsedZIndex()) {
+        // adjustRenderStyle() has already assigned a z-index of 0 if clip / filter is present or the element is the root element.
+        ASSERT(!style.hasClip());
+        ASSERT(!style.clipPath());
+        ASSERT(!style.hasFilter());
+        ASSERT(!svgElement.isOutermostSVGSVGElement());
+
+        auto isInnerSVGElement = [] (const SVGElement& svgElement) -> bool {
+            return svgElement.hasTagName(SVGNames::svgTag) && svgElement.parentNode() && is<SVGElement>(svgElement.parentNode());
+        };
+
+        if (svgElement.hasTagName(SVGNames::foreignObjectTag)
+            || svgElement.hasTagName(SVGNames::imageTag)
+            || svgElement.hasTagName(SVGNames::markerTag)
+            || svgElement.hasTagName(SVGNames::maskTag)
+            || svgElement.hasTagName(SVGNames::patternTag)
+            || svgElement.hasTagName(SVGNames::symbolTag)
+            || svgElement.hasTagName(SVGNames::useTag)
+            || (isInnerSVGElement(svgElement) && (style.overflowX() != Overflow::Visible || style.overflowY() != Overflow::Visible))
+            || style.hasPositionedMask())
+        style.setUsedZIndex(0);
+    }
+#endif
+
+    // (Legacy)RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
     // not be scaled again.
     if (svgElement.hasTagName(SVGNames::foreignObjectTag))
         style.setEffectiveZoom(RenderStyle::initialZoom());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to