Title: [294615] trunk
Revision
294615
Author
commit-qu...@webkit.org
Date
2022-05-21 16:16:37 -0700 (Sat, 21 May 2022)

Log Message

Perspective should not be affected by transform-origin
https://bugs.webkit.org/show_bug.cgi?id=211787
<rdar://problem/63143806>

Patch by Nikolas Zimmermann <nzimmerm...@igalia.com> on 2022-05-21
Reviewed by Simon Fraser.

Fix a number of issues related to perspective handling:
- 'perspective-origin' always used the border-box as reference box, when resolving
  length percentages, ignoring the choice of 'transform-box'. Fix that.

- Proper 'transform-box' awareness throghout RenderLayerBacking (few places with issue, e.g. perspectiveOrigin()
  affecting repaint & coverage rects)

- The chosen perspective transformation was not invariant under 'transform-origin' / 'transform-box'
  changes of the element A, that defines the perspective. However the perspective set on element A
  should only affect the rendering of its descendants: the choice of the 'transform-origin' / 'transform-box'
  of element A should have no effect on the perspective established for the children.

- Assure that 'transform-box' changes trigger GraphicLayer geometry updates: this fully fixes 'transform-box'
  support for composited elements, and brings its state on-par with non-composited elements (both support all kind of
  transform-box / transform-origin combinations on regular layers, clipped layers, scrolled layers).

This fixes the (not yet upstreamed) test web-platform-tests/css/css-transforms/animation/transform-box-will-change-transform-layer.html.

Prepared a new WPT test (see above) for upstreaming.

* Source/WebCore/animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::computeTransformedExtentViaTransformList const):
* Source/WebCore/rendering/RenderLayer.cpp:
(WebCore::RenderLayer::perspectiveTransform const):
(WebCore::RenderLayer::perspectiveOrigin const):
* Source/WebCore/rendering/RenderLayer.h:
* Source/WebCore/rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateTransform):
(WebCore::RenderLayerBacking::updateChildrenTransformAndAnchorPoint):
(WebCore::RenderLayerBacking::computeTransformOriginForPainting const): Deleted.
* Source/WebCore/rendering/RenderLayerBacking.h:
* Source/WebCore/rendering/RenderLayerCompositor.cpp:
(WebCore::recompositeChangeRequiresGeometryUpdate):
* Source/WebCore/rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::applySVGTransform const):
* Source/WebCore/rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::computePerspectiveOrigin const):
(WebCore::RenderStyle::applyPerspective const):
(WebCore::RenderStyle::computeTransformOrigin const):
(WebCore::RenderStyle::applyTransformOrigin const):
(WebCore::RenderStyle::unapplyTransformOrigin const):
(WebCore::RenderStyle::applyTransform const):
(WebCore::RenderStyle::applyMotionPathTransform const):
* Source/WebCore/rendering/style/RenderStyle.h:
* Source/WebCore/svg/SVGGraphicsElement.cpp:
(WebCore::SVGGraphicsElement::animatedLocalTransform const):
* LayoutTests/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt:
* LayoutTests/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt:
* LayoutTests/platform/glib/TestExpectations:
* LayoutTests/platform/ios-wk2/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt:
* LayoutTests/platform/ios/TestExpectations:
* LayoutTests/platform/mac-wk1/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt:
* LayoutTests/platform/mac/TestExpectations:
* LayoutTests/platform/win/TestExpectations:

Canonical link: https://commits.webkit.org/250841@main

Modified Paths

Diff

Modified: trunk/LayoutTests/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt (294614 => 294615)


--- trunk/LayoutTests/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt	2022-05-21 23:16:37 UTC (rev 294615)
@@ -24,9 +24,10 @@
                 (GraphicsLayer
                   (offsetFromRenderer width=1 height=1)
                   (position 1.00 1.00)
+                  (anchor 0.51 0.50)
                   (bounds 583.00 578.00)
                   (backingStoreAttached 1)
-                  (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [-307.50 -290.00 1.00 -1.00] [0.00 0.00 0.00 1.00])
+                  (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [-300.00 -290.00 1.00 -1.00] [0.00 0.00 0.00 1.00])
                   (children 1
                     (GraphicsLayer
                       (position 0.00 -400.00)

Modified: trunk/LayoutTests/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt (294614 => 294615)


--- trunk/LayoutTests/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt	2022-05-21 23:16:37 UTC (rev 294615)
@@ -29,8 +29,9 @@
           (children 2
             (GraphicsLayer
               (bounds origin 0.00 900.00)
+              (anchor 0.51 0.50)
               (bounds 585.00 500.00)
-              (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [2.93 2.50 1.00 -0.01] [0.00 0.00 0.00 1.00])
+              (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [3.00 2.50 1.00 -0.01] [0.00 0.00 0.00 1.00])
               (visible rect 0.00, 900.00 585.00 x 500.00)
               (coverage rect 0.00, 900.00 585.00 x 500.00)
               (intersects coverage rect 1)

Modified: trunk/LayoutTests/platform/glib/TestExpectations (294614 => 294615)


--- trunk/LayoutTests/platform/glib/TestExpectations	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/platform/glib/TestExpectations	2022-05-21 23:16:37 UTC (rev 294615)
@@ -663,9 +663,6 @@
 webkit.org/b/230277 imported/w3c/web-platform-tests/css/css-transforms/dynamic-fixed-pos-cb-change.html [ ImageOnlyFailure ]
 webkit.org/b/230277 imported/w3c/web-platform-tests/css/css-transforms/perspective-transforms-equivalence.html [ ImageOnlyFailure ]
 
-# 'transform-box' support is broken for composited elements.
-webkit.org/b/237553 imported/w3c/web-platform-tests/css/css-transforms/animation/transform-box-will-change-transform-layer.html [ ImageOnlyFailure ]
-
 webkit.org/b/237502 fast/dom/Range/getClientRects.html [ Failure ]
 webkit.org/b/237502 fast/multicol/newmulticol/hide-box-vertical-lr.html [ ImageOnlyFailure ]
 webkit.org/b/237502 imported/blink/fast/multicol/vertical-lr/float-big-line.html [ ImageOnlyFailure ]

Modified: trunk/LayoutTests/platform/ios/TestExpectations (294614 => 294615)


--- trunk/LayoutTests/platform/ios/TestExpectations	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2022-05-21 23:16:37 UTC (rev 294615)
@@ -3023,9 +3023,6 @@
 
 webkit.org/b/202958 css3/filters/svg-blur-filter-clipped.html [ ImageOnlyFailure ]
 
-# 'transform-box' support is broken for composited elements.
-webkit.org/b/237553 imported/w3c/web-platform-tests/css/css-transforms/animation/transform-box-will-change-transform-layer.html [ ImageOnlyFailure ]
-
 webkit.org/b/203305 imported/w3c/web-platform-tests/css/css-transitions/properties-value-001.html [ Pass Failure ]
 webkit.org/b/203305 [ Debug ] imported/w3c/web-platform-tests/css/css-transitions/properties-value-inherit-001.html [ Pass Failure ]
 webkit.org/b/203356 [ Debug ] imported/w3c/web-platform-tests/css/css-transitions/properties-value-003.html [ Pass Failure ]

Modified: trunk/LayoutTests/platform/ios-wk2/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt (294614 => 294615)


--- trunk/LayoutTests/platform/ios-wk2/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/platform/ios-wk2/compositing/tiling/coverage-adjustment-secondary-quad-mapping-expected.txt	2022-05-21 23:16:37 UTC (rev 294615)
@@ -23,9 +23,10 @@
                 (GraphicsLayer
                   (offsetFromRenderer width=1 height=1)
                   (position 1.00 1.00)
+                  (anchor 0.51 0.50)
                   (bounds 583.00 578.00)
                   (backingStoreAttached 1)
-                  (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [-307.50 -290.00 1.00 -1.00] [0.00 0.00 0.00 1.00])
+                  (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [-300.00 -290.00 1.00 -1.00] [0.00 0.00 0.00 1.00])
                   (children 1
                     (GraphicsLayer
                       (position 0.00 -400.00)

Modified: trunk/LayoutTests/platform/mac/TestExpectations (294614 => 294615)


--- trunk/LayoutTests/platform/mac/TestExpectations	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2022-05-21 23:16:37 UTC (rev 294615)
@@ -2197,9 +2197,6 @@
 
 webkit.org/b/230327 imported/w3c/web-platform-tests/css/css-transforms/crashtests/transform-marquee-resize-div-image-001.html [ Pass Failure ]
 
-# 'transform-box' support is broken for composited elements.
-webkit.org/b/237553 imported/w3c/web-platform-tests/css/css-transforms/animation/transform-box-will-change-transform-layer.html [ ImageOnlyFailure ]
-
 # rdar://83591040
 [ Monterey+ ] editing/mac/dictionary-lookup/dictionary-lookup-input.html [ Crash ]
 [ Monterey+ ] editing/mac/dictionary-lookup/dictionary-lookup-inside-selection.html [ Crash ]

Modified: trunk/LayoutTests/platform/mac-wk1/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt (294614 => 294615)


--- trunk/LayoutTests/platform/mac-wk1/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/platform/mac-wk1/compositing/tiling/perspective-on-scroller-tile-coverage-expected.txt	2022-05-21 23:16:37 UTC (rev 294615)
@@ -24,8 +24,9 @@
           (contentsScale 1.00)
           (children 1
             (GraphicsLayer
+              (anchor 0.51 0.50)
               (bounds 585.00 500.00)
-              (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [2.93 2.50 1.00 -0.01] [0.00 0.00 0.00 1.00])
+              (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [3.00 2.50 1.00 -0.01] [0.00 0.00 0.00 1.00])
               (visible rect 0.00, 0.00 585.00 x 500.00)
               (coverage rect 0.00, 0.00 585.00 x 500.00)
               (intersects coverage rect 1)

Modified: trunk/LayoutTests/platform/win/TestExpectations (294614 => 294615)


--- trunk/LayoutTests/platform/win/TestExpectations	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/LayoutTests/platform/win/TestExpectations	2022-05-21 23:16:37 UTC (rev 294615)
@@ -953,9 +953,6 @@
 webkit.org/b/149245 imported/w3c/web-platform-tests/css/css-multicol/multicol-span-all-block-sibling-003.xht [ Skip ]
 webkit.org/b/149245 imported/w3c/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht [ Skip ]
 
-# 'transform-box' support is broken for composited elements.
-webkit.org/b/237553 imported/w3c/web-platform-tests/css/css-transforms/animation/transform-box-will-change-transform-layer.html [ ImageOnlyFailure ]
-
 # TODO EXIF-resolution is not supported
 imported/w3c/web-platform-tests/density-size-correction/ [ Skip ]
 

Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (294614 => 294615)


--- trunk/Source/WebCore/animation/KeyframeEffect.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -1992,7 +1992,7 @@
 
     bool applyTransformOrigin = containsRotation(style.transform().operations()) || style.transform().affectedByTransformOrigin();
     if (applyTransformOrigin) {
-        transformOrigin = rendererBox.location() + floatPointForLengthPoint(style.transformOriginXY(), rendererBox.size());
+        transformOrigin = style.computeTransformOrigin(rendererBox).xy();
         // Ignore transformOriginZ because we'll bail if we encounter any 3D transforms.
         floatBounds.moveBy(-transformOrigin);
     }

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (294614 => 294615)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -1800,35 +1800,55 @@
     return positionOrOffsetChanged;
 }
 
-TransformationMatrix RenderLayer::perspectiveTransform(const LayoutRect& layerRect) const
+TransformationMatrix RenderLayer::perspectiveTransform() const
 {
-    // FIXME: [LBSE] Upstream transform support for RenderSVGModelObject derived renderers
-    if (!is<RenderBox>(renderer()))
+    if (!renderer().hasTransformRelatedProperty())
         return { };
 
-    auto& renderBox = downcast<RenderBox>(renderer());
-    if (!renderBox.hasTransformRelatedProperty())
-        return { };
-
-    const auto& style = renderBox.style();
+    const auto& style = renderer().style();
     if (!style.hasPerspective())
         return { };
 
-    auto referenceBoxRect = snapRectToDevicePixelsIfNeeded(renderer().transformReferenceBoxRect(style), renderer());
-    auto snappedLayerRect = snapRectToDevicePixelsIfNeeded(layerRect, renderer());
+    auto transformReferenceBoxRect = snapRectToDevicePixelsIfNeeded(renderer().transformReferenceBoxRect(style), renderer());
+    auto perspectiveOrigin = style.computePerspectiveOrigin(transformReferenceBoxRect);
 
-    auto perspectiveOrigin = referenceBoxRect.location() - toFloatSize(snappedLayerRect.location()) + floatPointForLengthPoint(style.perspectiveOrigin(), referenceBoxRect.size());
+    // In the regular case of a non-clipped, non-scrolled GraphicsLayer, all transformations
+    // (via CSS 'transform' / 'perspective') are applied with respect to a predefined anchor point,
+    // which depends on the chosen CSS 'transform-box' / 'transform-origin' properties.
+    //
+    // A transformation given by the CSS 'transform' property is applied, by translating
+    // to the 'transform origin', applying the transformation, and translating back.
+    // When an element specifies a CSS 'perspective' property, the perspective transformation matrix
+    // that's computed here is propagated to the GraphicsLayer by calling setChildrenTransform().
+    //
+    // However the GraphicsLayer platform implementations (e.g. CA on macOS) apply the children transform,
+    // defined on the parent, with respect to the anchor point of the parent, when rendering child elements.
+    // This is wrong, as the perspective transformation (applied to a child of the element defining the
+    // 3d effect), must be independant of the chosen transform-origin (the parents transform origin
+    // must not affect its children).
+    //
+    // To circumvent this, explicitely remove the transform-origin dependency in the perspective matrix.
+    auto transformOrigin = transformOriginPixelSnappedIfNeeded();
 
-    // A perspective origin of 0,0 makes the vanishing point in the center of the element.
-    // We want it to be in the top-left, so subtract half the height and width.
-    perspectiveOrigin -= snappedLayerRect.size() / 2.0f;
+    TransformationMatrix transform;
+    style.unapplyTransformOrigin(transform, transformOrigin);
+    style.applyPerspective(transform, renderer(), perspectiveOrigin);
+    style.applyTransformOrigin(transform, transformOrigin);
+    return transform;
+}
 
-    TransformationMatrix t;
-    t.translate(perspectiveOrigin.x(), perspectiveOrigin.y());
-    t.applyPerspective(style.usedPerspective(renderer()));
-    t.translate(-perspectiveOrigin.x(), -perspectiveOrigin.y());
+FloatPoint3D RenderLayer::transformOriginPixelSnappedIfNeeded() const
+{
+    if (!renderer().hasTransformRelatedProperty())
+        return { };
 
-    return t;
+    const auto& style = renderer().style();
+    auto referenceBoxRect = renderer().transformReferenceBoxRect(style);
+
+    auto origin = style.computeTransformOrigin(referenceBoxRect);
+    if (rendererNeedsPixelSnapping(renderer()))
+        origin.setXY(roundPointToDevicePixels(LayoutPoint(origin.xy()), renderer().document().deviceScaleFactor()));
+    return origin;
 }
 
 FloatPoint RenderLayer::perspectiveOrigin() const
@@ -1835,8 +1855,7 @@
 {
     if (!renderer().hasTransformRelatedProperty())
         return { };
-    // FIXME: This uses the wrong, transform-box unaware, geometry.
-    return floatPointForLengthPoint(renderer().style().perspectiveOrigin(), rendererBorderBoxRect().size());
+    return floatPointForLengthPoint(renderer().style().perspectiveOrigin(), renderer().transformReferenceBoxRect(renderer().style()).size());
 }
 
 static inline bool isContainerForPositioned(RenderLayer& layer, PositionType position, bool establishesTopLayer)

Modified: trunk/Source/WebCore/rendering/RenderLayer.h (294614 => 294615)


--- trunk/Source/WebCore/rendering/RenderLayer.h	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/RenderLayer.h	2022-05-21 23:16:37 UTC (rev 294615)
@@ -739,11 +739,12 @@
     TransformationMatrix currentTransform(OptionSet<RenderStyle::TransformOperationOption> = RenderStyle::allTransformOperations) const;
     TransformationMatrix renderableTransform(OptionSet<PaintBehavior>) const;
     
-    // Get the perspective transform, which is applied to transformed sublayers.
-    // Returns true if the layer has a -webkit-perspective.
+    // Get the children transform (to apply a perspective on children), which is applied to transformed sublayers, but not this layer.
+    // Returns true if the layer has a perspective.
     // Note that this transform has the perspective-origin baked in.
-    TransformationMatrix perspectiveTransform(const LayoutRect& layerRect) const;
+    TransformationMatrix perspectiveTransform() const;
     FloatPoint perspectiveOrigin() const;
+    FloatPoint3D transformOriginPixelSnappedIfNeeded() const;
     bool preserves3D() const { return renderer().style().preserves3D(); }
     bool has3DTransform() const { return m_transform && !m_transform->isAffine(); }
     bool hasTransformedAncestor() const { return m_hasTransformedAncestor; }

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (294614 => 294615)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -635,16 +635,11 @@
     m_graphicsLayer->setOpacity(compositingOpacity(style.opacity()));
 }
 
-void RenderLayerBacking::updateTransform(const RenderStyle&)
+void RenderLayerBacking::updateTransform(const RenderStyle& style)
 {
-    // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
-    // baked into it, and we don't want that.
     TransformationMatrix t;
-    if (m_owningLayer.hasTransform()) {
-        // FIXME: This uses the wrong, transform-box unaware, geometry.
-        renderer().applyTransform(t, renderer().style(), snapRectToDevicePixels(m_owningLayer.rendererBorderBoxRect(), deviceScaleFactor()), RenderStyle::individualTransformOperations);
-        makeMatrixRenderable(t, compositor().canRender3DTransforms());
-    }
+    if (m_owningLayer.hasTransform())
+        m_owningLayer.updateTransformFromStyle(t, style, RenderStyle::individualTransformOperations);
     
     if (m_contentsContainmentLayer) {
         m_contentsContainmentLayer->setTransform(t);
@@ -655,12 +650,18 @@
 
 void RenderLayerBacking::updateChildrenTransformAndAnchorPoint(const LayoutRect& primaryGraphicsLayerRect, LayoutSize offsetFromParentGraphicsLayer)
 {
+    auto defaultAnchorPoint = FloatPoint3D { 0.5, 0.5, 0 };
     if (!renderer().hasTransformRelatedProperty()) {
-        auto defaultAnchorPoint = FloatPoint3D { 0.5, 0.5, 0 };
         m_graphicsLayer->setAnchorPoint(defaultAnchorPoint);
         if (m_contentsContainmentLayer)
             m_contentsContainmentLayer->setAnchorPoint(defaultAnchorPoint);
 
+        if (m_childContainmentLayer)
+            m_childContainmentLayer->setAnchorPoint(defaultAnchorPoint);
+
+        if (m_scrollContainerLayer)
+            m_scrollContainerLayer->setAnchorPoint(defaultAnchorPoint);
+
         if (m_scrolledContentsLayer)
             m_scrolledContentsLayer->setPreserves3D(false);
         return;
@@ -667,8 +668,7 @@
     }
 
     const auto deviceScaleFactor = this->deviceScaleFactor();
-    auto borderBoxRect = m_owningLayer.rendererBorderBoxRect();
-    auto transformOrigin = computeTransformOriginForPainting(borderBoxRect);
+    auto transformOrigin = m_owningLayer.transformOriginPixelSnappedIfNeeded();
     auto layerOffset = roundPointToDevicePixels(toLayoutPoint(offsetFromParentGraphicsLayer), deviceScaleFactor);
     auto anchor = FloatPoint3D {
         primaryGraphicsLayerRect.width() ? ((layerOffset.x() - primaryGraphicsLayerRect.x()) + transformOrigin.x()) / primaryGraphicsLayerRect.width() : 0.5f,
@@ -683,11 +683,14 @@
 
     auto removeChildrenTransformFromLayers = [&](GraphicsLayer* layerToIgnore = nullptr) {
         auto* clippingLayer = this->clippingLayer();
-        if (clippingLayer && clippingLayer != layerToIgnore)
+        if (clippingLayer && clippingLayer != layerToIgnore) {
             clippingLayer->setChildrenTransform({ });
-        
+            clippingLayer->setAnchorPoint(defaultAnchorPoint);
+        }
+
         if (m_scrollContainerLayer && m_scrollContainerLayer != layerToIgnore) {
             m_scrollContainerLayer->setChildrenTransform({ });
+            m_scrollContainerLayer->setAnchorPoint(defaultAnchorPoint);
             m_scrolledContentsLayer->setPreserves3D(false);
         }
 
@@ -700,7 +703,7 @@
         return;
     }
 
-    auto layerForChildrenTransform = [&] {
+    auto layerForChildrenTransform = [&]() -> std::tuple<GraphicsLayer*, FloatRect> {
         if (m_scrollContainerLayer) {
             ASSERT(is<RenderBox>(renderer())); // Scroll container layers are only created for RenderBox derived renderers.
             return std::make_tuple(m_scrollContainerLayer.get(), scrollContainerLayerBox(downcast<RenderBox>(renderer())));
@@ -708,19 +711,26 @@
         if (auto* layer = clippingLayer())
             return std::make_tuple(layer, clippingLayerBox(renderer()));
 
-        return std::make_tuple(m_graphicsLayer.get(), borderBoxRect);
+        return std::make_tuple(m_graphicsLayer.get(), renderer().transformReferenceBoxRect());
     };
 
-    auto [layerForPerspective, perspectiveRelativeBox] = layerForChildrenTransform();
-    // FIXME: perspectiveRelativeBox isn't quite right here. This needs work: webkit.org/b/211787.
-    auto perspectiveTransform = owningLayer().perspectiveTransform(perspectiveRelativeBox);
-    
-    // If we have scrolling layers, we need the children transform on m_scrollContainerLayer to
-    // affect children of m_scrolledContentsLayer, so set setPreserves3D(true).
-    if (layerForPerspective == m_scrollContainerLayer)
-        m_scrolledContentsLayer->setPreserves3D(true);
-    
-    layerForPerspective->setChildrenTransform(perspectiveTransform);
+    auto [layerForPerspective, layerForPerspectiveRect] = layerForChildrenTransform();
+    if (layerForPerspective != m_graphicsLayer) {
+        // If we have scrolling layers, we need the children transform on m_scrollContainerLayer to
+        // affect children of m_scrolledContentsLayer, so set setPreserves3D(true).
+        if (layerForPerspective == m_scrollContainerLayer)
+            m_scrolledContentsLayer->setPreserves3D(true);
+
+        auto perspectiveAnchorPoint = FloatPoint3D {
+            layerForPerspectiveRect.width() ? (transformOrigin.x() - layerForPerspectiveRect.x()) / layerForPerspectiveRect.width() : 0.5f,
+            layerForPerspectiveRect.height() ? (transformOrigin.y() - layerForPerspectiveRect.y()) / layerForPerspectiveRect.height() : 0.5f,
+            transformOrigin.z()
+        };
+
+        layerForPerspective->setAnchorPoint(perspectiveAnchorPoint);
+    }
+
+    layerForPerspective->setChildrenTransform(m_owningLayer.perspectiveTransform());
     removeChildrenTransformFromLayers(layerForPerspective);
 }
 
@@ -2980,17 +2990,6 @@
     image->startAnimation();
 }
 
-FloatPoint3D RenderLayerBacking::computeTransformOriginForPainting(const LayoutRect& borderBox) const
-{
-    const RenderStyle& style = renderer().style();
-
-    FloatPoint3D origin;
-    origin.setXY(roundPointToDevicePixels(pointForLengthPoint(style.transformOriginXY(), borderBox.size()), deviceScaleFactor()));
-    origin.setZ(style.transformOriginZ());
-
-    return origin;
-}
-
 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
 LayoutSize RenderLayerBacking::contentOffsetInCompositingLayer() const
 {

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (294614 => 294615)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.h	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h	2022-05-21 23:16:37 UTC (rev 294615)
@@ -331,9 +331,6 @@
     void setBackgroundLayerPaintsFixedRootBackground(bool);
 
     LayoutSize contentOffsetInCompositingLayer() const;
-    // Result is transform origin in device pixels.
-    FloatPoint3D computeTransformOriginForPainting(const LayoutRect& borderBox) const;
-
     LayoutSize offsetRelativeToRendererOriginForDescendantLayers() const;
     
     void ensureClippingStackLayers(LayerAncestorClippingStack&);

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (294614 => 294615)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -1654,6 +1654,7 @@
         || oldStyle.translate() != newStyle.translate()
         || oldStyle.scale() != newStyle.scale()
         || oldStyle.rotate() != newStyle.rotate()
+        || oldStyle.transformBox() != newStyle.transformBox()
         || oldStyle.transformOriginX() != newStyle.transformOriginX()
         || oldStyle.transformOriginY() != newStyle.transformOriginY()
         || oldStyle.transformOriginZ() != newStyle.transformOriginZ()

Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (294614 => 294615)


--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -347,8 +347,10 @@
 
     FloatPoint3D originTranslate;
     if (options.contains(RenderStyle::TransformOperationOption::TransformOrigin) && affectedByTransformOrigin)
-        originTranslate = style.applyTransformOrigin(transform, boundingBox);
+        originTranslate = style.computeTransformOrigin(boundingBox);
 
+    style.applyTransformOrigin(transform, originTranslate);
+
     // CSS transforms take precedence over SVG transforms.
     if (hasCSSTransform)
         style.applyCSSTransform(transform, boundingBox, options);

Modified: trunk/Source/WebCore/rendering/style/RenderStyle.cpp (294614 => 294615)


--- trunk/Source/WebCore/rendering/style/RenderStyle.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -1491,22 +1491,43 @@
     return false;
 }
 
-FloatPoint3D RenderStyle::applyTransformOrigin(TransformationMatrix& transform, const FloatRect& boundingBox) const
+FloatPoint RenderStyle::computePerspectiveOrigin(const FloatRect& boundingBox) const
 {
-    // https://www.w3.org/TR/css-transforms-2/#ctm
-    // 2. Translate by the computed X, Y, and Z values of transform-origin.
+    return boundingBox.location() + floatPointForLengthPoint(perspectiveOrigin(), boundingBox.size());
+}
+
+void RenderStyle::applyPerspective(TransformationMatrix& transform, const RenderObject& renderer, const FloatPoint& originTranslate) const
+{
+    // https://www.w3.org/TR/css-transforms-2/#perspective
+    // The perspective matrix is computed as follows:
+    // 1. Start with the identity matrix.
+
+    // 2. Translate by the computed X and Y values of perspective-origin
+    transform.translate(originTranslate.x(), originTranslate.y());
+
+    // 3. Multiply by the matrix that would be obtained from the perspective() transform function, where the length is provided by the value of the perspective property
+    transform.applyPerspective(usedPerspective(renderer));
+
+    // 4. Translate by the negated computed X and Y values of perspective-origin
+    transform.translate(-originTranslate.x(), -originTranslate.y());
+}
+
+FloatPoint3D RenderStyle::computeTransformOrigin(const FloatRect& boundingBox) const
+{
     FloatPoint3D originTranslate;
     originTranslate.setXY(boundingBox.location() + floatPointForLengthPoint(transformOriginXY(), boundingBox.size()));
     originTranslate.setZ(transformOriginZ());
+    return originTranslate;
+}
+
+void RenderStyle::applyTransformOrigin(TransformationMatrix& transform, const FloatPoint3D& originTranslate) const
+{
     if (!originTranslate.isZero())
         transform.translate3d(originTranslate.x(), originTranslate.y(), originTranslate.z());
-    return originTranslate;
 }
 
 void RenderStyle::unapplyTransformOrigin(TransformationMatrix& transform, const FloatPoint3D& originTranslate) const
 {
-    // https://www.w3.org/TR/css-transforms-2/#ctm
-    // 8. Translate by the negated computed X, Y and Z values of transform-origin.
     if (!originTranslate.isZero())
         transform.translate3d(-originTranslate.x(), -originTranslate.y(), -originTranslate.z());
 }
@@ -1518,7 +1539,8 @@
         return;
     }
 
-    auto originTranslate = applyTransformOrigin(transform, boundingBox);
+    auto originTranslate = computeTransformOrigin(boundingBox);
+    applyTransformOrigin(transform, originTranslate);
     applyCSSTransform(transform, boundingBox, options);
     unapplyTransformOrigin(transform, originTranslate);
 }
@@ -1604,7 +1626,7 @@
     if (!offsetPath())
         return;
 
-    auto transformOrigin = floatPointForLengthPoint(transformOriginXY(), boundingBox.size()) + boundingBox.location();
+    auto transformOrigin = computeTransformOrigin(boundingBox).xy();
     auto anchor = transformOrigin;
     if (!offsetAnchor().x().isAuto())
         anchor = floatPointForLengthPoint(offsetAnchor(), boundingBox.size()) + boundingBox.location();

Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (294614 => 294615)


--- trunk/Source/WebCore/rendering/style/RenderStyle.h	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h	2022-05-21 23:16:37 UTC (rev 294615)
@@ -714,8 +714,14 @@
     static constexpr OptionSet<TransformOperationOption> individualTransformOperations = { TransformOperationOption::Translate, TransformOperationOption::Rotate, TransformOperationOption::Scale, TransformOperationOption::Offset };
 
     bool affectedByTransformOrigin() const;
-    FloatPoint3D applyTransformOrigin(TransformationMatrix&, const FloatRect& boundingBox) const;
+
+    FloatPoint computePerspectiveOrigin(const FloatRect& boundingBox) const;
+    void applyPerspective(TransformationMatrix&, const RenderObject&, const FloatPoint& originTranslate) const;
+
+    FloatPoint3D computeTransformOrigin(const FloatRect& boundingBox) const;
+    void applyTransformOrigin(TransformationMatrix&, const FloatPoint3D& originTranslate) const;
     void unapplyTransformOrigin(TransformationMatrix&, const FloatPoint3D& originTranslate) const;
+
     // applyTransform calls applyTransformOrigin(), then applyCSSTransform(), followed by unapplyTransformOrigin().
     void applyTransform(TransformationMatrix&, const FloatRect& boundingBox, OptionSet<TransformOperationOption> = allTransformOperations) const;
     void applyCSSTransform(TransformationMatrix&, const FloatRect& boundingBox, OptionSet<TransformOperationOption> = allTransformOperations) const;

Modified: trunk/Source/WebCore/svg/SVGGraphicsElement.cpp (294614 => 294615)


--- trunk/Source/WebCore/svg/SVGGraphicsElement.cpp	2022-05-21 19:26:27 UTC (rev 294614)
+++ trunk/Source/WebCore/svg/SVGGraphicsElement.cpp	2022-05-21 23:16:37 UTC (rev 294615)
@@ -107,8 +107,7 @@
 
     // If we didn't have the CSS "transform" property set, we must account for the "transform" attribute.
     if (!hasSpecifiedTransform && style) {
-        auto boundingBox = renderer()->transformReferenceBoxRect();
-        auto t = floatPointForLengthPoint(style->transformOriginXY(), boundingBox.size()) + boundingBox.location();
+        auto t = style->computeTransformOrigin(renderer()->transformReferenceBoxRect()).xy();
         matrix.translate(t);
         matrix *= transform().concatenate();
         matrix.translate(-t.x(), -t.y());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to