Log Message
When interpolating between transform lists partial prefix matches should not use matrix interpolation https://bugs.webkit.org/show_bug.cgi?id=235757 <rdar://problem/88477922>
Reviewed by Dean Jackson. LayoutTests/imported/w3c: * web-platform-tests/css/css-transforms/animation/list-interpolation-expected.txt: Mark subtests as passing. * web-platform-tests/css/css-transforms/animation/transform-composition-expected.txt: Ditto. * web-platform-tests/css/css-transforms/animation/transform-interpolation-004-expected.txt: Ditto. Source/WebCore: No new tests. This is covered by existing WPT tests. When interpolation between keyframes in transform animations, interpolate prefixes of compatible transform functions directly. For instance if there are three keyframes: 1. transform: rotateX(...) translateY(...) skew(...) 2. transform: rotateY(...) translateY(...) 3. transform: rotateZ(...) translateZ(...) matrix3d(...) There will be a directly interpolated rotation animation, a directly interpolated translation animation, and finally a matrix animation for the remaining functions. This is important for preserving transforms (such as full rotations) that are lost during matrix decompose and recompose operations. This change adds a new helper class SharedPrimitivesPrefix which is used to calculate the prefix of shared primitives that are shared between keyframes. Currently, the Core Animation backend only supports animation transformation primitives across the entire animation, so shared primitive prefixes must span the entire animation if an animation is accelerated. In the case that an animation is rendered in software, this prefix can simply be between the current next and previous keyframes. TransformOperations::blend is extended to blend any two TransformationOperations, which makes it the only blend function necessary for software animations, computed CSS values, and for the Nicosia backend, simplifying the interpolation code path. * animation/CSSPropertyAnimation.cpp: (WebCore::blendFunc): * animation/CSSPropertyBlendingClient.h: * animation/KeyframeEffect.cpp: (WebCore::KeyframeEffect::checkForMatchingTransformFunctionLists): (WebCore::KeyframeEffect::computeExtentOfTransformAnimation const): * animation/KeyframeEffect.h: * platform/graphics/GraphicsLayer.cpp: (WebCore::operationsAt): Deleted. (WebCore::GraphicsLayer::getSharedPrimitivesForTransformKeyframes): Deleted. * platform/graphics/GraphicsLayer.h: * platform/graphics/ca/GraphicsLayerCA.cpp: (WebCore::GraphicsLayerCA::appendToUncommittedAnimations): (WebCore::GraphicsLayerCA::createTransformAnimationsFromKeyframes): (WebCore::GraphicsLayerCA::setTransformAnimationKeyframes): * platform/graphics/ca/GraphicsLayerCA.h: * platform/graphics/nicosia/NicosiaAnimation.cpp: (Nicosia::applyTransformAnimation): (Nicosia::Animation::Animation): (Nicosia::Animation::operator=): (Nicosia::Animation::applyInternal): * platform/graphics/nicosia/NicosiaAnimation.h: * platform/graphics/texmap/GraphicsLayerTextureMapper.cpp: (WebCore::GraphicsLayerTextureMapper::addAnimation): * platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp: (WebCore::CoordinatedGraphicsLayer::addAnimation): * platform/graphics/transforms/TransformOperations.cpp: (WebCore::SharedPrimitivesPrefix::update): (WebCore::TransformOperations::blend const): (WebCore::TransformOperations::createBlendedMatrixOperationFromOperationsSuffix const): (WebCore::TransformOperations::operationsMatch const): Deleted. (WebCore::TransformOperations::updateSharedPrimitives const): Deleted. (WebCore::TransformOperations::blendByMatchingOperations const): Deleted. (WebCore::TransformOperations::blendByUsingMatrixInterpolation const): Deleted. * platform/graphics/transforms/TransformOperations.h: (WebCore::TransformOperations::apply const): (WebCore::SharedPrimitivesPrefix::hadIncompatibleTransformFunctions): (WebCore::SharedPrimitivesPrefix::primitives):
Modified Paths
- trunk/LayoutTests/imported/w3c/ChangeLog
- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/list-interpolation-expected.txt
- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-composition-expected.txt
- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-interpolation-004-expected.txt
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/animation/CSSPropertyAnimation.cpp
- trunk/Source/WebCore/animation/CSSPropertyBlendingClient.h
- trunk/Source/WebCore/animation/KeyframeEffect.cpp
- trunk/Source/WebCore/animation/KeyframeEffect.h
- trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp
- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h
- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
- trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.cpp
- trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.h
- trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
- trunk/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp
- trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.cpp
- trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h
Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (290666 => 290667)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2022-03-01 20:01:25 UTC (rev 290667)
@@ -1,3 +1,15 @@
+2022-03-01 Martin Robinson <[email protected]>
+
+ When interpolating between transform lists partial prefix matches should not use matrix interpolation
+ https://bugs.webkit.org/show_bug.cgi?id=235757
+ <rdar://problem/88477922>
+
+ Reviewed by Dean Jackson.
+
+ * web-platform-tests/css/css-transforms/animation/list-interpolation-expected.txt: Mark subtests as passing.
+ * web-platform-tests/css/css-transforms/animation/transform-composition-expected.txt: Ditto.
+ * web-platform-tests/css/css-transforms/animation/transform-interpolation-004-expected.txt: Ditto.
+
2022-03-01 Antoine Quint <[email protected]>
[web-animations] ::placeholder should not be a valid pseudo-element for a KeyframeEffect target
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/list-interpolation-expected.txt (290666 => 290667)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/list-interpolation-expected.txt 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/list-interpolation-expected.txt 2022-03-01 20:01:25 UTC (rev 290667)
@@ -43,10 +43,10 @@
PASS CSS Transitions with transition: all: property <transform> from [rotate3d(1, 0, 0, 360deg) translateX(100px)] to [rotate3d(0, 1, 0, -720deg) translateY(200px)] at (0.25) should be [rotate3d(0, 0, 1, 0deg) translate(75px, 50px)]
PASS CSS Animations: property <transform> from [rotate3d(1, 0, 0, 360deg) translateX(100px)] to [rotate3d(0, 1, 0, -720deg) translateY(200px)] at (0.25) should be [rotate3d(0, 0, 1, 0deg) translate(75px, 50px)]
PASS Web Animations: property <transform> from [rotate3d(1, 0, 0, 360deg) translateX(100px)] to [rotate3d(0, 1, 0, -720deg) translateY(200px)] at (0.25) should be [rotate3d(0, 0, 1, 0deg) translate(75px, 50px)]
-FAIL CSS Transitions: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1.25 , - 175 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1.25 , 175 , 0 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1.25 , - 175 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1.25 , 175 , 0 ) "
-FAIL CSS Animations: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1.25 , - 175 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1.25 , 175 , 0 ) "
-FAIL Web Animations: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1.25 , - 175 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1.25 , 175 , 0 ) "
+PASS CSS Transitions: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)]
+PASS CSS Transitions with transition: all: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)]
+PASS CSS Animations: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)]
+PASS Web Animations: property <transform> from [rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)]
PASS CSS Transitions: property <transform> from [scale(2) rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [matrix(2, 0, 0, 2, 250, 0)]
PASS CSS Transitions with transition: all: property <transform> from [scale(2) rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [matrix(2, 0, 0, 2, 250, 0)]
PASS CSS Animations: property <transform> from [scale(2) rotate(0deg) translate(100px)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [matrix(2, 0, 0, 2, 250, 0)]
@@ -55,24 +55,24 @@
PASS CSS Transitions with transition: all: property <transform> from [scale(2) rotate(0deg)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [matrix(2, 0, 0, 2, 100, 0)]
PASS CSS Animations: property <transform> from [scale(2) rotate(0deg)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [matrix(2, 0, 0, 2, 100, 0)]
PASS Web Animations: property <transform> from [scale(2) rotate(0deg)] to [rotate(720deg) scale(2) translate(200px)] at (0.25) should be [matrix(2, 0, 0, 2, 100, 0)]
-FAIL CSS Transitions: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL CSS Animations: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL Web Animations: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.25 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.25 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL CSS Transitions: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.75 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.75 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.75 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.75 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL CSS Animations: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.75 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.75 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL Web Animations: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)] assert_equals: expected "matrix ( - 1.75 , 0 , 0 , - 1 , 0 , 0 ) " but got "matrix ( 1.75 , 0 , 0 , 1 , 0 , 0 ) "
-FAIL CSS Transitions: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)] assert_equals: expected "matrix ( - 2.5 , 0 , 0 , 0 , 0 , 0 ) " but got "matrix ( - 1.94 , - 1.94 , - 1.59 , 1.59 , 0 , 0 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)] assert_equals: expected "matrix ( - 2.5 , 0 , 0 , 0 , 0 , 0 ) " but got "matrix ( - 1.94 , - 1.94 , - 1.59 , 1.59 , 0 , 0 ) "
-FAIL CSS Animations: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)] assert_equals: expected "matrix ( - 2.5 , 0 , 0 , 0 , 0 , 0 ) " but got "matrix ( - 1.94 , - 1.94 , - 1.59 , 1.59 , 0 , 0 ) "
-FAIL Web Animations: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)] assert_equals: expected "matrix ( - 2.5 , 0 , 0 , 0 , 0 , 0 ) " but got "matrix ( - 1.94 , - 1.94 , - 1.59 , 1.59 , 0 , 0 ) "
-FAIL CSS Transitions: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.59 , 1.59 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.59 , 1.59 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL CSS Animations: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.59 , 1.59 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL Web Animations: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.59 , 1.59 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL CSS Transitions: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.06 , 1.06 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.06 , 1.06 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL CSS Animations: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.06 , 1.06 , 1.94 , - 1.94 , 0 , 0 ) "
-FAIL Web Animations: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)] assert_equals: expected "matrix ( 0 , 0 , 0 , - 2.5 , 0 , 0 ) " but got "matrix ( 1.06 , 1.06 , 1.94 , - 1.94 , 0 , 0 ) "
+PASS CSS Transitions: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)]
+PASS CSS Transitions with transition: all: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)]
+PASS CSS Animations: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)]
+PASS Web Animations: property <transform> from [rotate(0deg) scaleX(1)] to [rotate(720deg) translateX(0px) scaleX(2)] at (0.25) should be [rotate(180deg) matrix(1.25, 0, 0, 1, 0, 0)]
+PASS CSS Transitions: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)]
+PASS CSS Transitions with transition: all: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)]
+PASS CSS Animations: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)]
+PASS Web Animations: property <transform> from [rotate(720deg) translateX(0px) scaleX(2)] to [rotate(0deg) scaleX(1)] at (0.25) should be [rotate(540deg) matrix(1.75, 0, 0, 1, 0, 0)]
+PASS CSS Transitions: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)]
+PASS CSS Transitions with transition: all: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)]
+PASS CSS Animations: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)]
+PASS Web Animations: property <transform> from [scaleX(-3) scaleY(2)] to [scaleY(-3) translateX(0px) scaleX(2)] at (0.25) should be [scale(-2, 0) matrix(1.25, 0, 0, 1.75, 0, 0)]
+PASS CSS Transitions: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)]
+PASS CSS Transitions with transition: all: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)]
+PASS CSS Animations: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)]
+PASS Web Animations: property <transform> from [scaleY(-3) translateX(0px) scaleX(2)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1.75, 0, 0, 1.25, 0, 0)]
+PASS CSS Transitions: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)]
+PASS CSS Transitions with transition: all: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)]
+PASS CSS Animations: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)]
+PASS Web Animations: property <transform> from [scaleY(-3) translateX(0px)] to [scaleX(-3) scaleY(2)] at (0.25) should be [scale(0, -2) matrix(1, 0, 0, 1.25, 0, 0)]
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-composition-expected.txt (290666 => 290667)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-composition-expected.txt 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-composition-expected.txt 2022-03-01 20:01:25 UTC (rev 290667)
@@ -1,11 +1,11 @@
-FAIL Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (-0.5) should be [rotateX(50deg) rotateY(50deg) translate(-40px, -80px)] assert_equals: expected "matrix3d ( 0.64 , 0.59 , - 0.49 , 0 , 0 , 0.64 , 0.77 , 0 , 0.77 , - 0.49 , 0.41 , 0 , - 25.71 , - 74.9 , - 41.59 , 1 ) " but got "matrix3d ( 0.18 , 0.86 , - 0.47 , 0 , 0.76 , 0.18 , 0.63 , 0 , 0.63 , - 0.47 , - 0.62 , 0 , 49.08 , 106.27 , 87.41 , 1 ) "
+PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (-0.5) should be [rotateX(50deg) rotateY(50deg) translate(-40px, -80px)]
PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0) should be [rotateX(100deg) rotateY(100deg) translate(10px, 20px)]
-FAIL Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0.25) should be [rotateX(125deg) rotateY(125deg) translate(35px, 70px)] assert_equals: expected "matrix3d ( - 0.57 , 0.67 , 0.47 , 0 , 0 , - 0.57 , 0.82 , 0 , 0.82 , 0.47 , 0.33 , 0 , - 20.08 , - 16.66 , 73.79 , 1 ) " but got "matrix3d ( - 0.5 , 0.81 , 0.31 , 0 , - 0.3 , - 0.5 , 0.81 , 0 , 0.81 , 0.31 , 0.49 , 0 , - 27.14 , - 43.8 , - 11.59 , 1 ) "
-FAIL Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0.5) should be [rotateX(150deg) rotateY(150deg) translate(60px, 120px)] assert_equals: expected "matrix3d ( - 0.87 , 0.25 , 0.43 , 0 , 0 , - 0.87 , 0.5 , 0 , 0.5 , 0.43 , 0.75 , 0 , - 51.96 , - 88.92 , 85.98 , 1 ) " but got "matrix3d ( - 0.79 , 0.56 , 0.25 , 0 , - 0.42 , - 0.79 , 0.45 , 0 , 0.45 , 0.25 , 0.85 , 0 , - 52.55 , - 93.82 , - 44.6 , 1 ) "
-FAIL Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0.75) should be [rotateX(175deg) rotateY(175deg) translate(85px, 170px)] assert_equals: expected "matrix3d ( - 1 , 0.01 , 0.09 , 0 , 0 , - 1 , 0.09 , 0 , 0.09 , 0.09 , 0.99 , 0 , - 84.68 , - 168.71 , 22.2 , 1 ) " but got "matrix3d ( - 0.95 , 0.3 , 0.02 , 0 , - 0.3 , - 0.95 , 0.02 , 0 , 0.02 , 0.02 , 1 , 0 , - 77.96 , - 143.84 , - 77.6 , 1 ) "
+PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0.25) should be [rotateX(125deg) rotateY(125deg) translate(35px, 70px)]
+PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0.5) should be [rotateX(150deg) rotateY(150deg) translate(60px, 120px)]
+PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (0.75) should be [rotateX(175deg) rotateY(175deg) translate(85px, 170px)]
PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (1) should be [rotateX(200deg) rotateY(200deg) translate(110px, 220px)]
-FAIL Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (1.5) should be [rotateX(250deg) rotateY(250deg) translate(160px, 320px)] assert_equals: expected "matrix3d ( - 0.34 , 0.88 , - 0.32 , 0 , 0 , - 0.34 , - 0.94 , 0 , - 0.94 , - 0.32 , 0.12 , 0 , - 54.72 , 31.84 , - 352.12 , 1 ) " but got "matrix3d ( - 0.45 , 0.16 , - 0.88 , 0 , 0.76 , - 0.45 , - 0.47 , 0 , - 0.47 , - 0.88 , 0.08 , 0 , - 154.18 , - 293.91 , - 176.6 , 1 ) "
+PASS Compositing: property <transform> underlying [rotateX(100deg) rotateY(100deg)] from add [translate(10px, 20px)] to replace [rotateX(200deg) rotateY(200deg) translate(110px, 220px)] at (1.5) should be [rotateX(250deg) rotateY(250deg) translate(160px, 320px)]
PASS Compositing: property <transform> underlying [rotateX(45deg)] from add [none] to add [rotateY(360deg)] at (-0.5) should be [rotateX(45deg) rotateY(-180deg)]
PASS Compositing: property <transform> underlying [rotateX(45deg)] from add [none] to add [rotateY(360deg)] at (0) should be [rotateX(45deg) rotateY(0deg)]
PASS Compositing: property <transform> underlying [rotateX(45deg)] from add [none] to add [rotateY(360deg)] at (0.25) should be [rotateX(45deg) rotateY(90deg)]
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-interpolation-004-expected.txt (290666 => 290667)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-interpolation-004-expected.txt 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transforms/animation/transform-interpolation-004-expected.txt 2022-03-01 20:01:25 UTC (rev 290667)
@@ -215,54 +215,54 @@
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [scaleY(2) skewX(2rad) perspective(500px)] at (0.75) should be [matrix3d(1, 0, 0, 0, -0.7525665307288518, 1.75, 0, 0, -0.005115979381443298, 0.002557989690721649, 0.9924999999999999, -0.002128247422680412, 2, -1, 3, 1.001298969072165)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [scaleY(2) skewX(2rad) perspective(500px)] at (1) should be [matrix3d(1, 0, 0, 0, -2.185039863261519, 2, 0, 0, 0, 0, 1, -0.002, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [scaleY(2) skewX(2rad) perspective(500px)] at (2) should be [matrix3d(1, 0, 0, 0, -11.227342763749263, 3, 0, 0, 0.021237113402061854, -0.010618556701030927, 1.03, -0.0014653608247422677, -8, 4, -12, 0.9861443298969074)]
-FAIL CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , - 0.01 , 0.95 , 0 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.03 , 0 , 0.96 , 0 , 12 , 4 , 16 , 1 ) "
+PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0) should be [translate3d(8px, -4px, 12px) matrix3d(1, 0, 0, 0, 1.55741, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.25) should be [translate3d(7px, -6px, 11px) matrix3d(1, 0, 0, 0, 1.46007, 1.25, 0, 0, 0, 0, 1, -0.002375, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.75) should be [translate3d(5px, -10px, 9px) matrix3d(1, 0, 0, 0, 0.681366, 1.75, 0, 0, 0, 0, 1, -0.002125, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (1) should be [translate3d(4px, -12px, 8px) matrix3d(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, -0.002, 0, 0, 0, 1)]
-FAIL CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.03 , 0.99 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.04 , 1 , 0 , 0 , - 20 , 4 , 1 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , - 0.01 , 0.95 , 0 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.03 , 0 , 0.96 , 0 , 12 , 4 , 16 , 1 ) "
+PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)]
+PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)]
PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0) should be [translate3d(8px, -4px, 12px) matrix3d(1, 0, 0, 0, 1.55741, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.25) should be [translate3d(7px, -6px, 11px) matrix3d(1, 0, 0, 0, 1.46007, 1.25, 0, 0, 0, 0, 1, -0.002375, 0, 0, 0, 1)]
PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.75) should be [translate3d(5px, -10px, 9px) matrix3d(1, 0, 0, 0, 0.681366, 1.75, 0, 0, 0, 0, 1, -0.002125, 0, 0, 0, 1)]
PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (1) should be [translate3d(4px, -12px, 8px) matrix3d(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, -0.002, 0, 0, 0, 1)]
-FAIL CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.03 , 0.99 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.04 , 1 , 0 , 0 , - 20 , 4 , 1 ) "
-FAIL CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , - 0.01 , 0.95 , 0 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.03 , 0 , 0.96 , 0 , 12 , 4 , 16 , 1 ) "
+PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)]
+PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)]
PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0) should be [translate3d(8px, -4px, 12px) matrix3d(1, 0, 0, 0, 1.55741, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.25) should be [translate3d(7px, -6px, 11px) matrix3d(1, 0, 0, 0, 1.46007, 1.25, 0, 0, 0, 0, 1, -0.002375, 0, 0, 0, 1)]
PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.75) should be [translate3d(5px, -10px, 9px) matrix3d(1, 0, 0, 0, 0.681366, 1.75, 0, 0, 0, 0, 1, -0.002125, 0, 0, 0, 1)]
PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (1) should be [translate3d(4px, -12px, 8px) matrix3d(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, -0.002, 0, 0, 0, 1)]
-FAIL CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.03 , 0.99 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.04 , 1 , 0 , 0 , - 20 , 4 , 1 ) "
-FAIL Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , - 0.01 , 0.95 , 0 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.03 , 0 , 0.96 , 0 , 12 , 4 , 16 , 1 ) "
+PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)]
+PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (-1) should be [translate3d(12px, 4px, 16px) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.003, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0) should be [translate3d(8px, -4px, 12px) matrix3d(1, 0, 0, 0, 1.55741, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.25) should be [translate3d(7px, -6px, 11px) matrix3d(1, 0, 0, 0, 1.46007, 1.25, 0, 0, 0, 0, 1, -0.002375, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (0.75) should be [translate3d(5px, -10px, 9px) matrix3d(1, 0, 0, 0, 0.681366, 1.75, 0, 0, 0, 0, 1, -0.002125, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (1) should be [translate3d(4px, -12px, 8px) matrix3d(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, -0.002, 0, 0, 0, 1)]
-FAIL Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.03 , 0.99 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 4.67 , 3 , 0 , 0 , 0 , 0.04 , 1 , 0 , 0 , - 20 , 4 , 1 ) "
-FAIL CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.06 , - 0.02 , 0.92 , - 0.01 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , 0.02 , 0.94 , 0 , 12 , 4 , 16 , 0.98 ) "
+PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) scaleY(2) perspective(500px)] at (2) should be [translate3d(0px, -20px, 4px) matrix3d(1, 0, 0, 0, -4.67222, 3, 0, 0, 0, 0, 1, -0.0015, 0, 0, 0, 1)]
+PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0) should be [translate3d(8px, -4px, 12px) skewX(1rad) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
-FAIL CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 3.76 , 1.25 , 0 , 0 , - 0.01 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0.78 , 1.25 , 0 , 0 , - 0.02 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) "
-FAIL CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 9.66 , 1.75 , 0 , 0 , 0 , 0.01 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 2.19 , 1.75 , 0 , 0 , - 0.01 , 0 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) "
+PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)]
+PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (1) should be [translate3d(4px, -12px, 8px) skewX(2rad) matrix(1, 0, 0, 2, 0, 0)]
-FAIL CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 0.43 , 3 , 0 , 0 , 0 , - 0.05 , 1.01 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 17.78 , 3 , 0 , 0 , 0.02 , - 0.01 , 1.03 , 0 , 0 , - 20 , 4 , 0.98 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.06 , - 0.02 , 0.92 , - 0.01 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , 0.02 , 0.94 , 0 , 12 , 4 , 16 , 0.98 ) "
+PASS CSS Transitions: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)]
+PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)]
PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0) should be [translate3d(8px, -4px, 12px) skewX(1rad) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
-FAIL CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 3.76 , 1.25 , 0 , 0 , - 0.01 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0.78 , 1.25 , 0 , 0 , - 0.02 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) "
-FAIL CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 9.66 , 1.75 , 0 , 0 , 0 , 0.01 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 2.19 , 1.75 , 0 , 0 , - 0.01 , 0 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) "
+PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)]
+PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)]
PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (1) should be [translate3d(4px, -12px, 8px) skewX(2rad) matrix(1, 0, 0, 2, 0, 0)]
-FAIL CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 0.43 , 3 , 0 , 0 , 0 , - 0.05 , 1.01 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 17.78 , 3 , 0 , 0 , 0.02 , - 0.01 , 1.03 , 0 , 0 , - 20 , 4 , 0.98 ) "
-FAIL CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.06 , - 0.02 , 0.92 , - 0.01 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , 0.02 , 0.94 , 0 , 12 , 4 , 16 , 0.98 ) "
+PASS CSS Transitions with transition: all: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)]
+PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)]
PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0) should be [translate3d(8px, -4px, 12px) skewX(1rad) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
-FAIL CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 3.76 , 1.25 , 0 , 0 , - 0.01 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0.78 , 1.25 , 0 , 0 , - 0.02 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) "
-FAIL CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 9.66 , 1.75 , 0 , 0 , 0 , 0.01 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 2.19 , 1.75 , 0 , 0 , - 0.01 , 0 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) "
+PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)]
+PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)]
PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (1) should be [translate3d(4px, -12px, 8px) skewX(2rad) matrix(1, 0, 0, 2, 0, 0)]
-FAIL CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 0.43 , 3 , 0 , 0 , 0 , - 0.05 , 1.01 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 17.78 , 3 , 0 , 0 , 0.02 , - 0.01 , 1.03 , 0 , 0 , - 20 , 4 , 0.98 ) "
-FAIL Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.06 , - 0.02 , 0.92 , - 0.01 , 12 , 4 , 16 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0.04 , 0.02 , 0.94 , 0 , 12 , 4 , 16 , 0.98 ) "
+PASS CSS Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)]
+PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (-1) should be [translate3d(12px, 4px, 16px) skewX(0rad) matrix3d(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.005, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0) should be [translate3d(8px, -4px, 12px) skewX(1rad) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.0025, 0, 0, 0, 1)]
-FAIL Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , 3.76 , 1.25 , 0 , 0 , - 0.01 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , 0.78 , 1.25 , 0 , 0 , - 0.02 , 0.01 , 0.98 , 0 , 7 , - 6 , 11 , 1 ) "
-FAIL Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 9.66 , 1.75 , 0 , 0 , 0 , 0.01 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 2.19 , 1.75 , 0 , 0 , - 0.01 , 0 , 0.99 , 0 , 5 , - 10 , 9 , 1 ) "
+PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.25) should be [translate3d(7px, -6px, 11px) skewX(1.25rad) matrix3d(1, 0, 0, 0, 0, 1.25, 0, 0, 0, 0, 1, -0.001875, 0, 0, 0, 1)]
+PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (0.75) should be [translate3d(5px, -10px, 9px) skewX(1.75rad) matrix3d(1, 0, 0, 0, 0, 1.75, 0, 0, 0, 0, 1, -0.000625, 0, 0, 0, 1)]
PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (1) should be [translate3d(4px, -12px, 8px) skewX(2rad) matrix(1, 0, 0, 2, 0, 0)]
-FAIL Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)] assert_equals: expected "matrix3d ( 1 , 0 , 0 , 0 , - 0.43 , 3 , 0 , 0 , 0 , - 0.05 , 1.01 , 0 , 0 , - 20 , 4 , 1 ) " but got "matrix3d ( 1 , 0 , 0 , 0 , - 17.78 , 3 , 0 , 0 , 0.02 , - 0.01 , 1.03 , 0 , 0 , - 20 , 4 , 0.98 ) "
+PASS Web Animations: property <transform> from [translate3d(8px, -4px, 12px) skewX(1rad) perspective(400px)] to [translate3d(4px, -12px, 8px) skewX(2rad) scaleY(2)] at (2) should be [translate3d(0px, -20px, 4px) skewX(3rad) matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0.0025, 0, 0, 0, 1)]
PASS CSS Transitions: property <transform> from [translate3D(100px, 200px, 300px)] to [none] at (-1) should be [matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 200, 400, 600, 1)]
PASS CSS Transitions: property <transform> from [translate3D(100px, 200px, 300px)] to [none] at (0) should be [matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 200, 300, 1)]
PASS CSS Transitions: property <transform> from [translate3D(100px, 200px, 300px)] to [none] at (0.25) should be [matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 75, 150, 225, 1)]
Modified: trunk/Source/WebCore/ChangeLog (290666 => 290667)
--- trunk/Source/WebCore/ChangeLog 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/ChangeLog 2022-03-01 20:01:25 UTC (rev 290667)
@@ -1,3 +1,76 @@
+2022-03-01 Martin Robinson <[email protected]>
+
+ When interpolating between transform lists partial prefix matches should not use matrix interpolation
+ https://bugs.webkit.org/show_bug.cgi?id=235757
+ <rdar://problem/88477922>
+
+ Reviewed by Dean Jackson.
+
+ No new tests. This is covered by existing WPT tests.
+
+ When interpolation between keyframes in transform animations, interpolate prefixes of
+ compatible transform functions directly. For instance if there are three keyframes:
+
+ 1. transform: rotateX(...) translateY(...) skew(...)
+ 2. transform: rotateY(...) translateY(...)
+ 3. transform: rotateZ(...) translateZ(...) matrix3d(...)
+
+ There will be a directly interpolated rotation animation, a directly interpolated
+ translation animation, and finally a matrix animation for the remaining functions.
+ This is important for preserving transforms (such as full rotations) that are lost
+ during matrix decompose and recompose operations.
+
+ This change adds a new helper class SharedPrimitivesPrefix which is used to calculate
+ the prefix of shared primitives that are shared between keyframes.
+
+ Currently, the Core Animation backend only supports animation transformation primitives
+ across the entire animation, so shared primitive prefixes must span the entire animation
+ if an animation is accelerated. In the case that an animation is rendered in software,
+ this prefix can simply be between the current next and previous keyframes.
+
+ TransformOperations::blend is extended to blend any two TransformationOperations, which
+ makes it the only blend function necessary for software animations, computed CSS values,
+ and for the Nicosia backend, simplifying the interpolation code path.
+
+ * animation/CSSPropertyAnimation.cpp:
+ (WebCore::blendFunc):
+ * animation/CSSPropertyBlendingClient.h:
+ * animation/KeyframeEffect.cpp:
+ (WebCore::KeyframeEffect::checkForMatchingTransformFunctionLists):
+ (WebCore::KeyframeEffect::computeExtentOfTransformAnimation const):
+ * animation/KeyframeEffect.h:
+ * platform/graphics/GraphicsLayer.cpp:
+ (WebCore::operationsAt): Deleted.
+ (WebCore::GraphicsLayer::getSharedPrimitivesForTransformKeyframes): Deleted.
+ * platform/graphics/GraphicsLayer.h:
+ * platform/graphics/ca/GraphicsLayerCA.cpp:
+ (WebCore::GraphicsLayerCA::appendToUncommittedAnimations):
+ (WebCore::GraphicsLayerCA::createTransformAnimationsFromKeyframes):
+ (WebCore::GraphicsLayerCA::setTransformAnimationKeyframes):
+ * platform/graphics/ca/GraphicsLayerCA.h:
+ * platform/graphics/nicosia/NicosiaAnimation.cpp:
+ (Nicosia::applyTransformAnimation):
+ (Nicosia::Animation::Animation):
+ (Nicosia::Animation::operator=):
+ (Nicosia::Animation::applyInternal):
+ * platform/graphics/nicosia/NicosiaAnimation.h:
+ * platform/graphics/texmap/GraphicsLayerTextureMapper.cpp:
+ (WebCore::GraphicsLayerTextureMapper::addAnimation):
+ * platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp:
+ (WebCore::CoordinatedGraphicsLayer::addAnimation):
+ * platform/graphics/transforms/TransformOperations.cpp:
+ (WebCore::SharedPrimitivesPrefix::update):
+ (WebCore::TransformOperations::blend const):
+ (WebCore::TransformOperations::createBlendedMatrixOperationFromOperationsSuffix const):
+ (WebCore::TransformOperations::operationsMatch const): Deleted.
+ (WebCore::TransformOperations::updateSharedPrimitives const): Deleted.
+ (WebCore::TransformOperations::blendByMatchingOperations const): Deleted.
+ (WebCore::TransformOperations::blendByUsingMatrixInterpolation const): Deleted.
+ * platform/graphics/transforms/TransformOperations.h:
+ (WebCore::TransformOperations::apply const):
+ (WebCore::SharedPrimitivesPrefix::hadIncompatibleTransformFunctions):
+ (WebCore::SharedPrimitivesPrefix::primitives):
+
2022-03-01 Commit Queue <[email protected]>
Unreviewed, reverting r290619.
Modified: trunk/Source/WebCore/animation/CSSPropertyAnimation.cpp (290666 => 290667)
--- trunk/Source/WebCore/animation/CSSPropertyAnimation.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/animation/CSSPropertyAnimation.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -169,9 +169,7 @@
return resultOperations;
}
auto boxSize = is<RenderBox>(context.client->renderer()) ? downcast<RenderBox>(*context.client->renderer()).borderBoxRect().size() : LayoutSize();
- if (context.client->transformFunctionListsMatch())
- return to.blendByMatchingOperations(from, context, boxSize);
- return to.blendByUsingMatrixInterpolation(from, context, boxSize);
+ return to.blend(from, context, boxSize, context.client->transformFunctionListPrefix());
}
static RefPtr<ScaleTransformOperation> blendFunc(ScaleTransformOperation* from, ScaleTransformOperation* to, const CSSPropertyBlendingContext& context)
Modified: trunk/Source/WebCore/animation/CSSPropertyBlendingClient.h (290666 => 290667)
--- trunk/Source/WebCore/animation/CSSPropertyBlendingClient.h 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/animation/CSSPropertyBlendingClient.h 2022-03-01 20:01:25 UTC (rev 290667)
@@ -25,6 +25,8 @@
#pragma once
+#include <optional>
+
namespace WebCore {
class RenderElement;
@@ -36,7 +38,7 @@
virtual RenderElement* renderer() const = 0;
virtual const RenderStyle& currentStyle() const = 0;
virtual bool filterFunctionListsMatch() const = 0;
- virtual bool transformFunctionListsMatch() const = 0;
+ virtual std::optional<unsigned> transformFunctionListPrefix() const = 0;
#if ENABLE(FILTERS_LEVEL_2)
virtual bool backdropFilterFunctionListsMatch() const = 0;
#endif
Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (290666 => 290667)
--- trunk/Source/WebCore/animation/KeyframeEffect.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -913,20 +913,16 @@
void KeyframeEffect::checkForMatchingTransformFunctionLists()
{
- m_transformFunctionListsMatch = false;
-
- if (m_blendingKeyframes.size() < 2 || !m_blendingKeyframes.containsProperty(CSSPropertyTransform))
+ if (m_blendingKeyframes.size() < 2 || !m_blendingKeyframes.containsProperty(CSSPropertyTransform)) {
+ m_transformFunctionListsMatchPrefix = 0;
return;
+ }
- Vector<TransformOperation::OperationType> sharedPrimitives;
- sharedPrimitives.reserveInitialCapacity(m_blendingKeyframes[0].style()->transform().operations().size());
+ SharedPrimitivesPrefix prefix;
+ for (const auto& keyframe : m_blendingKeyframes)
+ prefix.update(keyframe.style()->transform());
- for (const auto& keyframe : m_blendingKeyframes) {
- if (!keyframe.style()->transform().updateSharedPrimitives(sharedPrimitives))
- return;
- }
-
- m_transformFunctionListsMatch = true;
+ m_transformFunctionListsMatchPrefix = prefix.primitives().size();
}
bool KeyframeEffect::checkForMatchingFilterFunctionLists(CSSPropertyID propertyID, const std::function<const FilterOperations& (const RenderStyle&)>& filtersGetter) const
@@ -1941,7 +1937,7 @@
auto keyframeBounds = bounds;
bool canCompute;
- if (transformFunctionListsMatch())
+ if (transformFunctionListPrefix() > 0)
canCompute = computeTransformedExtentViaTransformList(rendererBox, *style, keyframeBounds);
else
canCompute = computeTransformedExtentViaMatrix(rendererBox, *style, keyframeBounds);
Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (290666 => 290667)
--- trunk/Source/WebCore/animation/KeyframeEffect.h 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h 2022-03-01 20:01:25 UTC (rev 290667)
@@ -140,7 +140,14 @@
bool isAboutToRunAccelerated() const { return m_acceleratedPropertiesState != AcceleratedProperties::None && m_lastRecordedAcceleratedAction != AcceleratedAction::Stop; }
bool filterFunctionListsMatch() const override { return m_filterFunctionListsMatch; }
- bool transformFunctionListsMatch() const override { return m_transformFunctionListsMatch; }
+
+ // The CoreAnimation animation code can only use direct function interpolation when all keyframes share the same
+ // prefix of shared transform function primitives, whereas software animations simply calls blend(...) which can do
+ // direct interpolation based on the function list of any two particular keyframes. The prefix serves as a way to
+ // make sure that the results of blend(...) can be made to return the same results as rendered by the hardware
+ // animation code.
+ std::optional<unsigned> transformFunctionListPrefix() const override { return (!preventsAcceleration()) ? std::optional<unsigned>(m_transformFunctionListsMatchPrefix) : std::nullopt; }
+
#if ENABLE(FILTERS_LEVEL_2)
bool backdropFilterFunctionListsMatch() const override { return m_backdropFilterFunctionListsMatch; }
#endif
@@ -241,7 +248,7 @@
RunningAccelerated m_runningAccelerated;
bool m_needsForcedLayout { false };
bool m_triggersStackingContext { false };
- bool m_transformFunctionListsMatch { false };
+ size_t m_transformFunctionListsMatchPrefix { 0 };
bool m_filterFunctionListsMatch { false };
#if ENABLE(FILTERS_LEVEL_2)
bool m_backdropFilterFunctionListsMatch { false };
Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -711,37 +711,6 @@
return firstIndex;
}
-static inline const TransformOperations& operationsAt(const KeyframeValueList& valueList, size_t index)
-{
- return static_cast<const TransformAnimationValue&>(valueList.at(index)).value();
-}
-
-// A sequence of keyframes with a list of transforms can be represented without matrix interpolation
-// if each transform is compatible with all other transforms at the same index in other keyframes.
-// Two transforms are compatible if they share a primitive defined by the CSS Transforms Level 2
-// specification. For instance, the shared primitive of a translateX and translate3D operation is
-// TransformOperation::TRANSLATE_3D. This function returns true if the TransformOperations in each
-// keyframe share a primitive operation type and stores the compatible OperationTypes in
-// sharedPrimitives. If the keyframes do not share a list of compatible primitives, false is
-// returned.
-bool GraphicsLayer::getSharedPrimitivesForTransformKeyframes(const KeyframeValueList& valueList, Vector<TransformOperation::OperationType>& sharedPrimitives)
-{
- ASSERT(animatedPropertyIsTransformOrRelated(valueList.property()));
-
- if (valueList.size() < 2)
- return false;
-
- sharedPrimitives.clear();
- sharedPrimitives.reserveInitialCapacity(operationsAt(valueList, 0).size());
-
- for (size_t i = 0; i < valueList.size(); ++i) {
- if (!operationsAt(valueList, i).updateSharedPrimitives(sharedPrimitives))
- return false;
- }
-
- return true;
-}
-
double GraphicsLayer::backingStoreMemoryEstimate() const
{
if (!drawsContent())
Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h 2022-03-01 20:01:25 UTC (rev 290667)
@@ -667,11 +667,6 @@
// Given a KeyframeValueList containing filterOperations, return true if the operations are valid.
static int validateFilterOperations(const KeyframeValueList&);
- // Given a list of TransformAnimationValues keyframes, place a list of primitive operations which can
- // represent the transform functions of every keyframe in the sharedPrimitives out parameter and return
- // true. If the keyframes do not share compatible functions, return false.
- static bool getSharedPrimitivesForTransformKeyframes(const KeyframeValueList&, Vector<TransformOperation::OperationType>& sharedPrimitives);
-
virtual bool shouldRepaintOnSizeChange() const { return drawsContent(); }
void removeFromParentInternal();
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -3458,22 +3458,19 @@
return true;
}
-bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const Vector<TransformOperation::OperationType>& operations, const Animation* animation, const String& animationName, const FloatSize& boxSize, unsigned animationIndex, Seconds timeOffset, bool isMatrixAnimation, bool keyframesShouldUseAnimationWideTimingFunction)
+bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, TransformOperation::OperationType operationType, const Animation* animation, const String& animationName, const FloatSize& boxSize, unsigned animationIndex, Seconds timeOffset, bool isMatrixAnimation, bool keyframesShouldUseAnimationWideTimingFunction)
{
- // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation.
- auto transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations[animationIndex];
-
RefPtr<PlatformCAAnimation> caAnimation;
bool validMatrices = true;
if (isKeyframe(valueList)) {
caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), false, keyframesShouldUseAnimationWideTimingFunction);
- validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize, keyframesShouldUseAnimationWideTimingFunction);
+ validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, operationType, isMatrixAnimation, boxSize, keyframesShouldUseAnimationWideTimingFunction);
} else {
if (animation->timingFunction()->isSpringTimingFunction())
caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), false, keyframesShouldUseAnimationWideTimingFunction);
else
caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), false, keyframesShouldUseAnimationWideTimingFunction);
- validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
+ validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, operationType, isMatrixAnimation, boxSize);
}
if (!validMatrices)
@@ -3487,19 +3484,33 @@
{
ASSERT(animatedPropertyIsTransformOrRelated(valueList.property()));
- Vector<TransformOperation::OperationType> sharedPrimitives;
- bool isMatrixAnimation = !getSharedPrimitivesForTransformKeyframes(valueList, sharedPrimitives);
- unsigned numOperations = !isMatrixAnimation ? sharedPrimitives.size() : 1;
+ // https://www.w3.org/TR/css-transforms-1/#interpolation-of-transforms
+ // In the CSS Transform Level 1 and 2 Specification some transform functions can share a compatible transform
+ // function primitive. For instance, the shared primitive of a translateX and translate3D operation is
+ // TransformOperation::TRANSLATE_3D. When the transform function list of every keyframe in an animation
+ // shares the same transform function primitive, we should interpolate between them without resorting
+ // to matrix decomposition. The remaining parts of the transform function list should be interpolated
+ // using matrix decomposition. The code below finds the shared primitives in this prefix.
+ // FIXME: Currently, this only supports situations where every keyframe shares the same prefix of shared
+ // transformation primitives, but the specification says direct interpolation should be determined by
+ // the primitives shared between any two adjacent keyframes.
+ SharedPrimitivesPrefix prefix;
+ for (size_t i = 0; i < valueList.size(); ++i)
+ prefix.update(static_cast<const TransformAnimationValue&>(valueList.at(i)).value());
- bool validMatrices = true;
- for (unsigned animationIndex = 0; animationIndex < numOperations; ++animationIndex) {
- if (!appendToUncommittedAnimations(valueList, sharedPrimitives, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation, keyframesShouldUseAnimationWideTimingFunction)) {
- validMatrices = false;
- break;
- }
+ const auto& primitives = prefix.primitives();
+ unsigned numberOfSharedPrimitives = valueList.size() > 1 ? primitives.size() : 0;
+ for (unsigned animationIndex = 0; animationIndex < numberOfSharedPrimitives; ++animationIndex) {
+ if (!appendToUncommittedAnimations(valueList, primitives[animationIndex], animation, animationName, boxSize, animationIndex, timeOffset, false /* isMatrixAnimation */, keyframesShouldUseAnimationWideTimingFunction))
+ return false;
}
- return validMatrices;
+ if (!prefix.hadIncompatibleTransformFunctions())
+ return true;
+
+ // If there were any incompatible transform functions, they will be appended to the animation list
+ // as a single combined transformation matrix animation.
+ return appendToUncommittedAnimations(valueList, TransformOperation::MATRIX_3D, animation, animationName, boxSize, primitives.size(), timeOffset, true /* isMatrixAnimation */, keyframesShouldUseAnimationWideTimingFunction);
}
bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction)
@@ -3778,10 +3789,9 @@
const TransformAnimationValue& curValue = static_cast<const TransformAnimationValue&>(valueList.at(index));
keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
- TransformationMatrix transform;
-
if (isMatrixAnimation) {
- curValue.value().apply(boxSize, transform);
+ TransformationMatrix transform;
+ curValue.value().apply(functionIndex, boxSize, transform);
// If any matrix is singular, CA won't animate it correctly. So fall back to software animation
if (!transform.isInvertible())
@@ -3803,8 +3813,6 @@
getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
transformationMatrixValues.append(value);
}
-
- curValue.value().apply(boxSize, transform);
}
if (i < (valueList.size() - 1))
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2022-03-01 20:01:25 UTC (rev 290667)
@@ -530,7 +530,7 @@
moveOrCopyAnimations(Copy, fromLayer, toLayer);
}
- bool appendToUncommittedAnimations(const KeyframeValueList&, const Vector<TransformOperation::OperationType>& operations, const Animation*, const String& animationName, const FloatSize& boxSize, unsigned animationIndex, Seconds timeOffset, bool isMatrixAnimation, bool keyframesShouldUseAnimationWideTimingFunction);
+ bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperation::OperationType, const Animation*, const String& animationName, const FloatSize& boxSize, unsigned animationIndex, Seconds timeOffset, bool isMatrixAnimation, bool keyframesShouldUseAnimationWideTimingFunction);
bool appendToUncommittedAnimations(const KeyframeValueList&, const FilterOperation*, const Animation*, const String& animationName, int animationIndex, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction);
enum LayerChange : uint64_t {
Modified: trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.cpp (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -109,7 +109,7 @@
return fromOpacity + progress * (toOpacity - fromOpacity);
}
-static TransformationMatrix applyTransformAnimation(const TransformOperations& from, const TransformOperations& to, double progress, const FloatSize& boxSize, bool listsMatch)
+static TransformationMatrix applyTransformAnimation(const TransformOperations& from, const TransformOperations& to, double progress, const FloatSize& boxSize)
{
TransformationMatrix matrix;
@@ -125,35 +125,7 @@
return matrix;
}
- // If we have incompatible operation lists, we blend the resulting matrices.
- if (!listsMatch) {
- TransformationMatrix fromMatrix;
- to.apply(boxSize, matrix);
- from.apply(boxSize, fromMatrix);
- matrix.blend(fromMatrix, progress);
- return matrix;
- }
-
- // Animation to "-webkit-transform: none".
- if (!to.size()) {
- TransformOperations blended(from);
- for (auto& operation : blended.operations())
- operation->blend(nullptr, progress, true)->apply(matrix, boxSize);
- return matrix;
- }
-
- // Animation from "-webkit-transform: none".
- if (!from.size()) {
- TransformOperations blended(to);
- for (auto& operation : blended.operations())
- operation->blend(nullptr, 1 - progress, true)->apply(matrix, boxSize);
- return matrix;
- }
-
- // Normal animation with a matching operation list.
- TransformOperations blended(to);
- for (size_t i = 0; i < blended.operations().size(); ++i)
- blended.operations()[i]->blend(from.at(i), progress, !from.at(i))->apply(matrix, boxSize);
+ to.blend(from, progress, LayoutSize { boxSize }).apply(boxSize, matrix);
return matrix;
}
@@ -166,7 +138,7 @@
return CubicBezierTimingFunction::defaultTimingFunction();
}
-Animation::Animation(const String& name, const KeyframeValueList& keyframes, const FloatSize& boxSize, const WebCore::Animation& animation, bool listsMatch, MonotonicTime startTime, Seconds pauseTime, AnimationState state)
+Animation::Animation(const String& name, const KeyframeValueList& keyframes, const FloatSize& boxSize, const WebCore::Animation& animation, MonotonicTime startTime, Seconds pauseTime, AnimationState state)
: m_name(name.isSafeToSendToAnotherThread() ? name : name.isolatedCopy())
, m_keyframes(keyframes)
, m_boxSize(boxSize)
@@ -175,7 +147,6 @@
, m_duration(animation.duration())
, m_direction(animation.direction())
, m_fillsForwards(animation.fillsForwards())
- , m_listsMatch(listsMatch)
, m_startTime(startTime)
, m_pauseTime(pauseTime)
, m_totalRunningTime(0_s)
@@ -193,7 +164,6 @@
, m_duration(other.m_duration)
, m_direction(other.m_direction)
, m_fillsForwards(other.m_fillsForwards)
- , m_listsMatch(other.m_listsMatch)
, m_startTime(other.m_startTime)
, m_pauseTime(other.m_pauseTime)
, m_totalRunningTime(other.m_totalRunningTime)
@@ -212,7 +182,6 @@
m_duration = other.m_duration;
m_direction = other.m_direction;
m_fillsForwards = other.m_fillsForwards;
- m_listsMatch = other.m_listsMatch;
m_startTime = other.m_startTime;
m_pauseTime = other.m_pauseTime;
m_totalRunningTime = other.m_totalRunningTime;
@@ -311,7 +280,7 @@
{
switch (m_keyframes.property()) {
case AnimatedPropertyTransform:
- applicationResults.transform = applyTransformAnimation(static_cast<const TransformAnimationValue&>(from).value(), static_cast<const TransformAnimationValue&>(to).value(), progress, m_boxSize, m_listsMatch);
+ applicationResults.transform = applyTransformAnimation(static_cast<const TransformAnimationValue&>(from).value(), static_cast<const TransformAnimationValue&>(to).value(), progress, m_boxSize);
return;
case AnimatedPropertyOpacity:
applicationResults.opacity = applyOpacityAnimation((static_cast<const FloatAnimationValue&>(from).value()), (static_cast<const FloatAnimationValue&>(to).value()), progress);
Modified: trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.h (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.h 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/nicosia/NicosiaAnimation.h 2022-03-01 20:01:25 UTC (rev 290667)
@@ -42,7 +42,7 @@
Animation()
: m_keyframes(WebCore::AnimatedPropertyInvalid)
{ }
- Animation(const String&, const WebCore::KeyframeValueList&, const WebCore::FloatSize&, const WebCore::Animation&, bool, MonotonicTime, Seconds, AnimationState);
+ Animation(const String&, const WebCore::KeyframeValueList&, const WebCore::FloatSize&, const WebCore::Animation&, MonotonicTime, Seconds, AnimationState);
WEBCORE_EXPORT Animation(const Animation&);
Animation& operator=(const Animation&);
@@ -71,7 +71,6 @@
double m_duration;
WebCore::Animation::AnimationDirection m_direction;
bool m_fillsForwards;
- bool m_listsMatch;
MonotonicTime m_startTime;
Seconds m_pauseTime;
Seconds m_totalRunningTime;
Modified: trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -611,14 +611,8 @@
return false;
}
- bool listsMatch = false;
- if (valueList.property() == AnimatedPropertyTransform) {
- Vector<TransformOperation::OperationType> unusedOperations;
- listsMatch = !!getSharedPrimitivesForTransformKeyframes(valueList, unusedOperations);
- }
-
const MonotonicTime currentTime = MonotonicTime::now();
- m_animations.add(Nicosia::Animation(keyframesName, valueList, boxSize, *anim, listsMatch, currentTime - Seconds(timeOffset), 0_s, Nicosia::Animation::AnimationState::Playing));
+ m_animations.add(Nicosia::Animation(keyframesName, valueList, boxSize, *anim, currentTime - Seconds(timeOffset), 0_s, Nicosia::Animation::AnimationState::Playing));
// m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
if (Seconds(timeOffset) > 0_s)
m_animationStartTime = currentTime;
Modified: trunk/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -1399,7 +1399,6 @@
if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
return false;
- bool listsMatch = false;
switch (valueList.property()) {
#if ENABLE(FILTERS_LEVEL_2)
case AnimatedPropertyWebkitBackdropFilter:
@@ -1414,12 +1413,8 @@
return false;
break;
}
- case AnimatedPropertyTransform: {
- Vector<TransformOperation::OperationType> unusedOperations;
- listsMatch = !!getSharedPrimitivesForTransformKeyframes(valueList, unusedOperations);
- break;
- }
case AnimatedPropertyOpacity:
+ case AnimatedPropertyTransform:
break;
default:
return false;
@@ -1426,7 +1421,7 @@
}
m_lastAnimationStartTime = MonotonicTime::now() - Seconds(delayAsNegativeTimeOffset);
- m_animations.add(Nicosia::Animation(keyframesName, valueList, boxSize, *anim, listsMatch, m_lastAnimationStartTime, 0_s, Nicosia::Animation::AnimationState::Playing));
+ m_animations.add(Nicosia::Animation(keyframesName, valueList, boxSize, *anim, m_lastAnimationStartTime, 0_s, Nicosia::Animation::AnimationState::Playing));
m_animationStartedTimer.startOneShot(0_s);
didChangeAnimations();
return true;
Modified: trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.cpp (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.cpp 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.cpp 2022-03-01 20:01:25 UTC (rev 290667)
@@ -50,41 +50,30 @@
return true;
}
-bool TransformOperations::operationsMatch(const TransformOperations& other) const
+void SharedPrimitivesPrefix::update(const TransformOperations& operations)
{
- // If functions at the same index don't share a blending primitive, the lists don't match.
- // When the lists are different sizes, the missing functions in the shorter list are treated
- // as identity functions.
- size_t minimumLength = std::min(operations().size(), other.operations().size());
- for (size_t i = 0; i < minimumLength; ++i) {
- if (!operations()[i]->sharedPrimitiveType(other.operations()[i].get()))
- return false;
- }
- return true;
-}
+ size_t maxIteration = operations.operations().size();
+ if (m_indexOfFirstMismatch.has_value())
+ maxIteration = std::min(*m_indexOfFirstMismatch, maxIteration);
-bool TransformOperations::updateSharedPrimitives(Vector<TransformOperation::OperationType>& sharedPrimitives) const
-{
- for (size_t i = 0; i < operations().size(); ++i) {
- const auto* operation = at(i);
+ for (size_t i = 0; i < maxIteration; ++i) {
+ const auto* operation = operations.at(i);
// If we haven't seen an operation at this index before, we can simply use our primitive type.
- if (i >= sharedPrimitives.size()) {
- ASSERT(i == sharedPrimitives.size());
- sharedPrimitives.append(operation->primitiveType());
+ if (i >= m_primitives.size()) {
+ ASSERT(i == m_primitives.size());
+ m_primitives.append(operation->primitiveType());
continue;
}
- if (auto sharedPrimitive = operation->sharedPrimitiveType(sharedPrimitives[i]))
- sharedPrimitives[i] = *sharedPrimitive;
+ if (auto sharedPrimitive = operation->sharedPrimitiveType(m_primitives[i]))
+ m_primitives[i] = *sharedPrimitive;
else {
- // FIXME: This should handle prefix matches and then fall back to matrix interpolation for the rest
- // of the list. See: https://bugs.webkit.org/show_bug.cgi?id=235757
- return false;
+ m_indexOfFirstMismatch = i;
+ m_primitives.shrink(i);
+ return;
}
}
-
- return true;
}
bool TransformOperations::affectedByTransformOrigin() const
@@ -101,7 +90,7 @@
return (from.hasMatrixOperation() || hasMatrixOperation()) && (!from.isInvertible(boxSize) || !isInvertible(boxSize));
}
-TransformOperations TransformOperations::blendByMatchingOperations(const TransformOperations& from, const BlendingContext& context, const LayoutSize& boxSize) const
+TransformOperations TransformOperations::blend(const TransformOperations& from, const BlendingContext& context, const LayoutSize& boxSize, std::optional<unsigned> prefixLength) const
{
TransformOperations result;
@@ -108,15 +97,19 @@
unsigned fromOperationCount = from.operations().size();
unsigned toOperationCount = operations().size();
unsigned maxOperationCount = std::max(fromOperationCount, toOperationCount);
-
- if (shouldFallBackToDiscreteAnimation(from, boxSize))
- return blendByUsingMatrixInterpolation(from, context, boxSize);
-
+
+ if (shouldFallBackToDiscreteAnimation(from, boxSize)) {
+ result.operations().append(createBlendedMatrixOperationFromOperationsSuffix(from, 0, context, boxSize));
+ return result;
+ }
+
for (unsigned i = 0; i < maxOperationCount; i++) {
RefPtr<TransformOperation> fromOperation = (i < fromOperationCount) ? from.operations()[i].get() : nullptr;
RefPtr<TransformOperation> toOperation = (i < toOperationCount) ? operations()[i].get() : nullptr;
- if (fromOperation && toOperation && !fromOperation->sharedPrimitiveType(toOperation.get()))
- return blendByUsingMatrixInterpolation(from, context, boxSize);
+ if ((prefixLength && i >= *prefixLength) || (fromOperation && toOperation && !fromOperation->sharedPrimitiveType(toOperation.get()))) {
+ result.operations().append(createBlendedMatrixOperationFromOperationsSuffix(from, i, context, boxSize));
+ return result;
+ }
RefPtr<TransformOperation> blendedOperation;
if (fromOperation && toOperation)
@@ -135,40 +128,24 @@
return result;
}
-TransformOperations TransformOperations::blendByUsingMatrixInterpolation(const TransformOperations& from, const BlendingContext& context, const LayoutSize& boxSize) const
+RefPtr<TransformOperation> TransformOperations::createBlendedMatrixOperationFromOperationsSuffix(const TransformOperations& from, unsigned start, const BlendingContext& context, const LayoutSize& referenceBoxSize) const
{
- TransformOperations result;
-
- // Convert the TransformOperations into matrices
TransformationMatrix fromTransform;
+ from.apply(start, referenceBoxSize, fromTransform);
TransformationMatrix toTransform;
- from.apply(boxSize, fromTransform);
- apply(boxSize, toTransform);
-
+ apply(start, referenceBoxSize, toTransform);
+
auto progress = context.progress;
auto compositeOperation = context.compositeOperation;
- if (shouldFallBackToDiscreteAnimation(from, boxSize)) {
+ if (shouldFallBackToDiscreteAnimation(from, referenceBoxSize)) {
progress = progress < 0.5 ? 0 : 1;
compositeOperation = CompositeOperation::Replace;
}
+
toTransform.blend(fromTransform, progress, compositeOperation);
- // Append the result
- result.operations().append(Matrix3DTransformOperation::create(toTransform));
-
- return result;
+ return Matrix3DTransformOperation::create(toTransform);
}
-TransformOperations TransformOperations::blend(const TransformOperations& from, const BlendingContext& context, const LayoutSize& size) const
-{
- if (from == *this)
- return *this;
-
- if (from.size() && from.operationsMatch(*this))
- return blendByMatchingOperations(from, context, size);
-
- return blendByUsingMatrixInterpolation(from, context, size);
-}
-
TextStream& operator<<(TextStream& ts, const TransformOperations& ops)
{
for (const auto& operation : ops.operations())
Modified: trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h (290666 => 290667)
--- trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h 2022-03-01 19:53:41 UTC (rev 290666)
+++ trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h 2022-03-01 20:01:25 UTC (rev 290667)
@@ -44,11 +44,13 @@
return !(*this == o);
}
- void apply(const FloatSize& sz, TransformationMatrix& t) const
+ void apply(const FloatSize& size, TransformationMatrix& matrix) const { apply(0, size, matrix); }
+ void apply(unsigned start, const FloatSize& size, TransformationMatrix& matrix) const
{
- for (unsigned i = 0; i < m_operations.size(); ++i)
- m_operations[i]->apply(t, sz);
+ for (unsigned i = start; i < m_operations.size(); ++i)
+ m_operations[i]->apply(matrix, size);
}
+
// Return true if any of the operation types are 3D operation types (even if the
// values describe affine transforms)
@@ -77,13 +79,6 @@
return true;
}
- bool operationsMatch(const TransformOperations&) const;
-
- // Find a list of transform primitives for the given TransformOperations which are compatible with the primitives
- // stored in sharedPrimitives. The results are written back into sharedPrimitives. This returns false if any element
- // of TransformOperation does not have a shared primitive, otherwise it returns true.
- bool updateSharedPrimitives(Vector<TransformOperation::OperationType>& sharedPrimitives) const;
-
void clear()
{
m_operations.clear();
@@ -105,14 +100,31 @@
bool shouldFallBackToDiscreteAnimation(const TransformOperations&, const LayoutSize&) const;
- TransformOperations blendByMatchingOperations(const TransformOperations& from, const BlendingContext&, const LayoutSize&) const;
- TransformOperations blendByUsingMatrixInterpolation(const TransformOperations& from, const BlendingContext&, const LayoutSize&) const;
- TransformOperations blend(const TransformOperations& from, const BlendingContext&, const LayoutSize&) const;
+ RefPtr<TransformOperation> createBlendedMatrixOperationFromOperationsSuffix(const TransformOperations& from, unsigned start, const BlendingContext&, const LayoutSize& referenceBoxSize) const;
+ TransformOperations blend(const TransformOperations& from, const BlendingContext&, const LayoutSize&, std::optional<unsigned> prefixLength = std::nullopt) const;
private:
Vector<RefPtr<TransformOperation>> m_operations;
};
+// SharedPrimitivesPrefix is used to find a shared prefix of transform function primitives (as
+// defined by CSS Transforms Level 1 & 2). Given a series of TransformOperations in the keyframes
+// of an animation. After update() is called with the TransformOperations of every keyframe,
+// primitive() will return the prefix of primitives that are shared by all keyframes passed
+// to update().
+class SharedPrimitivesPrefix {
+public:
+ SharedPrimitivesPrefix() = default;
+ virtual ~SharedPrimitivesPrefix() = default;
+ void update(const TransformOperations&);
+ bool hadIncompatibleTransformFunctions() { return m_indexOfFirstMismatch.has_value(); }
+ const Vector<TransformOperation::OperationType>& primitives() { return m_primitives; }
+
+private:
+ std::optional<size_t> m_indexOfFirstMismatch;
+ Vector<TransformOperation::OperationType> m_primitives;
+};
+
WTF::TextStream& operator<<(WTF::TextStream&, const TransformOperations&);
} // namespace WebCore
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
