1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "config.h" 26 27 #include "core/platform/graphics/chromium/AnimationTranslationUtil.h" 28 29 #include "core/platform/animation/CSSAnimationData.h" 30 #include "core/platform/graphics/GraphicsLayer.h" // For KeyframeValueList 31 #include "core/platform/graphics/IntSize.h" 32 #include "core/platform/graphics/transforms/Matrix3DTransformOperation.h" 33 #include "core/platform/graphics/transforms/RotateTransformOperation.h" 34 #include "core/platform/graphics/transforms/ScaleTransformOperation.h" 35 #include "core/platform/graphics/transforms/TransformOperations.h" 36 #include "core/platform/graphics/transforms/TranslateTransformOperation.h" 37 #include "wtf/RefPtr.h" 38 #include <gtest/gtest.h> 39 #include "public/platform/WebAnimation.h" 40 41 using namespace WebCore; 42 using namespace WebKit; 43 44 namespace { 45 46 bool animationCanBeTranslated(const KeyframeValueList& values, CSSAnimationData* animation) 47 { 48 IntSize boxSize; 49 return createWebAnimation(values, animation, 0, 0, boxSize); 50 } 51 52 TEST(AnimationTranslationUtilTest, createOpacityAnimation) 53 { 54 const double duration = 1; 55 WebCore::KeyframeValueList values(AnimatedPropertyOpacity); 56 values.insert(adoptPtr(new FloatAnimationValue(0, 0))); 57 values.insert(adoptPtr(new FloatAnimationValue(duration, 1))); 58 59 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 60 animation->setDuration(duration); 61 62 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 63 } 64 65 TEST(AnimationTranslationUtilTest, createTransformAnimation) 66 { 67 const double duration = 1; 68 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 69 70 TransformOperations operations1; 71 operations1.operations().append(TranslateTransformOperation::create(Length(2, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 72 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 73 74 TransformOperations operations2; 75 operations2.operations().append(TranslateTransformOperation::create(Length(4, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 76 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 77 78 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 79 animation->setDuration(duration); 80 81 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 82 } 83 84 TEST(AnimationTranslationUtilTest, createTransformAnimationWithBigRotation) 85 { 86 const double duration = 1; 87 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 88 89 TransformOperations operations1; 90 operations1.operations().append(RotateTransformOperation::create(0, TransformOperation::Rotate)); 91 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 92 93 TransformOperations operations2; 94 operations2.operations().append(RotateTransformOperation::create(270, TransformOperation::Rotate)); 95 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 96 97 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 98 animation->setDuration(duration); 99 100 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 101 } 102 103 TEST(AnimationTranslationUtilTest, createTransformAnimationWithBigRotationAndEmptyTransformOperationList) 104 { 105 const double duration = 1; 106 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 107 108 TransformOperations operations1; 109 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 110 111 TransformOperations operations2; 112 operations2.operations().append(RotateTransformOperation::create(270, TransformOperation::Rotate)); 113 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 114 115 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 116 animation->setDuration(duration); 117 118 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 119 } 120 121 TEST(AnimationTranslationUtilTest, createTransformAnimationWithRotationInvolvingNegativeAngles) 122 { 123 const double duration = 1; 124 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 125 126 TransformOperations operations1; 127 operations1.operations().append(RotateTransformOperation::create(-330, TransformOperation::Rotate)); 128 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 129 130 TransformOperations operations2; 131 operations2.operations().append(RotateTransformOperation::create(-320, TransformOperation::Rotate)); 132 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 133 134 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 135 animation->setDuration(duration); 136 137 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 138 } 139 140 TEST(AnimationTranslationUtilTest, createTransformAnimationWithSmallRotationInvolvingLargeAngles) 141 { 142 const double duration = 1; 143 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 144 145 TransformOperations operations1; 146 operations1.operations().append(RotateTransformOperation::create(270, TransformOperation::Rotate)); 147 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 148 149 TransformOperations operations2; 150 operations2.operations().append(RotateTransformOperation::create(360, TransformOperation::Rotate)); 151 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 152 153 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 154 animation->setDuration(duration); 155 156 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 157 } 158 159 TEST(AnimationTranslationUtilTest, createTransformAnimationWithNonDecomposableMatrix) 160 { 161 const double duration = 1; 162 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 163 164 TransformationMatrix matrix1; 165 TransformOperations operations1; 166 operations1.operations().append(Matrix3DTransformOperation::create(matrix1)); 167 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 168 169 TransformationMatrix matrix2; 170 matrix2.setM11(0); 171 TransformOperations operations2; 172 operations2.operations().append(Matrix3DTransformOperation::create(matrix2)); 173 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 174 175 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 176 animation->setDuration(duration); 177 178 EXPECT_FALSE(animationCanBeTranslated(values, animation.get())); 179 } 180 181 TEST(AnimationTranslationUtilTest, createTransformAnimationWithNonInvertibleTransform) 182 { 183 const double duration = 1; 184 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 185 186 TransformOperations operations1; 187 operations1.operations().append(ScaleTransformOperation::create(1, 1, 1, TransformOperation::Scale3D)); 188 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 189 190 TransformOperations operations2; 191 operations2.operations().append(ScaleTransformOperation::create(1, 0, 1, TransformOperation::Scale3D)); 192 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 193 194 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 195 animation->setDuration(duration); 196 197 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 198 } 199 200 TEST(AnimationTranslationUtilTest, createReversedAnimation) 201 { 202 const double duration = 1; 203 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 204 205 TransformOperations operations1; 206 operations1.operations().append(TranslateTransformOperation::create(Length(2, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 207 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 208 209 TransformOperations operations2; 210 operations2.operations().append(TranslateTransformOperation::create(Length(4, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 211 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 212 213 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 214 animation->setDuration(duration); 215 animation->setDirection(CSSAnimationData::AnimationDirectionReverse); 216 217 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 218 } 219 220 TEST(AnimationTranslationUtilTest, createAlternatingAnimation) 221 { 222 const double duration = 1; 223 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 224 225 TransformOperations operations1; 226 operations1.operations().append(TranslateTransformOperation::create(Length(2, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 227 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 228 229 TransformOperations operations2; 230 operations2.operations().append(TranslateTransformOperation::create(Length(4, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 231 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 232 233 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 234 animation->setDuration(duration); 235 animation->setDirection(CSSAnimationData::AnimationDirectionAlternate); 236 animation->setIterationCount(2); 237 238 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 239 } 240 241 TEST(AnimationTranslationUtilTest, createReversedAlternatingAnimation) 242 { 243 const double duration = 1; 244 WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); 245 246 TransformOperations operations1; 247 operations1.operations().append(TranslateTransformOperation::create(Length(2, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 248 values.insert(adoptPtr(new TransformAnimationValue(0, &operations1))); 249 250 TransformOperations operations2; 251 operations2.operations().append(TranslateTransformOperation::create(Length(4, WebCore::Fixed), Length(0, WebCore::Fixed), TransformOperation::TranslateX)); 252 values.insert(adoptPtr(new TransformAnimationValue(duration, &operations2))); 253 254 RefPtr<CSSAnimationData> animation = CSSAnimationData::create(); 255 animation->setDuration(duration); 256 animation->setDirection(CSSAnimationData::AnimationDirectionAlternateReverse); 257 animation->setIterationCount(2); 258 259 EXPECT_TRUE(animationCanBeTranslated(values, animation.get())); 260 } 261 262 } 263 264