| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "core/animation/AnimationStack.h" | |
| 6 | |
| 7 #include "core/animation/AnimationClock.h" | |
| 8 #include "core/animation/CompositorPendingAnimations.h" | |
| 9 #include "core/animation/DocumentTimeline.h" | |
| 10 #include "core/animation/ElementAnimations.h" | |
| 11 #include "core/animation/KeyframeEffectModel.h" | |
| 12 #include "core/animation/LegacyStyleInterpolation.h" | |
| 13 #include "core/animation/animatable/AnimatableDouble.h" | |
| 14 #include "core/testing/DummyPageHolder.h" | |
| 15 #include "testing/gtest/include/gtest/gtest.h" | |
| 16 #include <memory> | |
| 17 | |
| 18 namespace blink { | |
| 19 | |
| 20 class AnimationAnimationStackTest : public ::testing::Test { | |
| 21 protected: | |
| 22 virtual void SetUp() { | |
| 23 pageHolder = DummyPageHolder::create(); | |
| 24 document = &pageHolder->document(); | |
| 25 document->animationClock().resetTimeForTesting(); | |
| 26 timeline = DocumentTimeline::create(document.get()); | |
| 27 element = document->createElement("foo"); | |
| 28 } | |
| 29 | |
| 30 Animation* play(KeyframeEffect* effect, double startTime) { | |
| 31 Animation* animation = timeline->play(effect); | |
| 32 animation->setStartTime(startTime * 1000); | |
| 33 animation->update(TimingUpdateOnDemand); | |
| 34 return animation; | |
| 35 } | |
| 36 | |
| 37 void updateTimeline(double time) { | |
| 38 document->animationClock().updateTime(document->timeline().zeroTime() + | |
| 39 time); | |
| 40 timeline->serviceAnimations(TimingUpdateForAnimationFrame); | |
| 41 } | |
| 42 | |
| 43 size_t sampledEffectCount() { | |
| 44 return element->ensureElementAnimations() | |
| 45 .animationStack() | |
| 46 .m_sampledEffects.size(); | |
| 47 } | |
| 48 | |
| 49 EffectModel* makeEffectModel(CSSPropertyID id, | |
| 50 PassRefPtr<AnimatableValue> value) { | |
| 51 AnimatableValueKeyframeVector keyframes(2); | |
| 52 keyframes[0] = AnimatableValueKeyframe::create(); | |
| 53 keyframes[0]->setOffset(0.0); | |
| 54 keyframes[0]->setPropertyValue(id, value.get()); | |
| 55 keyframes[1] = AnimatableValueKeyframe::create(); | |
| 56 keyframes[1]->setOffset(1.0); | |
| 57 keyframes[1]->setPropertyValue(id, value.get()); | |
| 58 return AnimatableValueKeyframeEffectModel::create(keyframes); | |
| 59 } | |
| 60 | |
| 61 InertEffect* makeInertEffect(EffectModel* effect) { | |
| 62 Timing timing; | |
| 63 timing.fillMode = Timing::FillMode::BOTH; | |
| 64 return InertEffect::create(effect, timing, false, 0); | |
| 65 } | |
| 66 | |
| 67 KeyframeEffect* makeKeyframeEffect(EffectModel* effect, | |
| 68 double duration = 10) { | |
| 69 Timing timing; | |
| 70 timing.fillMode = Timing::FillMode::BOTH; | |
| 71 timing.iterationDuration = duration; | |
| 72 return KeyframeEffect::create(element.get(), effect, timing); | |
| 73 } | |
| 74 | |
| 75 AnimatableValue* interpolationValue( | |
| 76 const ActiveInterpolationsMap& activeInterpolations, | |
| 77 CSSPropertyID id) { | |
| 78 Interpolation& interpolation = | |
| 79 *activeInterpolations.get(PropertyHandle(id)).at(0); | |
| 80 return toLegacyStyleInterpolation(interpolation).currentValue().get(); | |
| 81 } | |
| 82 | |
| 83 std::unique_ptr<DummyPageHolder> pageHolder; | |
| 84 Persistent<Document> document; | |
| 85 Persistent<DocumentTimeline> timeline; | |
| 86 Persistent<Element> element; | |
| 87 }; | |
| 88 | |
| 89 TEST_F(AnimationAnimationStackTest, ElementAnimationsSorted) { | |
| 90 play(makeKeyframeEffect( | |
| 91 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(1))), | |
| 92 10); | |
| 93 play(makeKeyframeEffect( | |
| 94 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(2))), | |
| 95 15); | |
| 96 play(makeKeyframeEffect( | |
| 97 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(3))), | |
| 98 5); | |
| 99 ActiveInterpolationsMap result = AnimationStack::activeInterpolations( | |
| 100 &element->elementAnimations()->animationStack(), 0, 0, | |
| 101 KeyframeEffectReadOnly::DefaultPriority); | |
| 102 EXPECT_EQ(1u, result.size()); | |
| 103 EXPECT_TRUE(interpolationValue(result, CSSPropertyFontSize) | |
| 104 ->equals(AnimatableDouble::create(3).get())); | |
| 105 } | |
| 106 | |
| 107 TEST_F(AnimationAnimationStackTest, NewAnimations) { | |
| 108 play(makeKeyframeEffect( | |
| 109 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(1))), | |
| 110 15); | |
| 111 play(makeKeyframeEffect( | |
| 112 makeEffectModel(CSSPropertyZIndex, AnimatableDouble::create(2))), | |
| 113 10); | |
| 114 HeapVector<Member<const InertEffect>> newAnimations; | |
| 115 InertEffect* inert1 = makeInertEffect( | |
| 116 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(3))); | |
| 117 InertEffect* inert2 = makeInertEffect( | |
| 118 makeEffectModel(CSSPropertyZIndex, AnimatableDouble::create(4))); | |
| 119 newAnimations.append(inert1); | |
| 120 newAnimations.append(inert2); | |
| 121 ActiveInterpolationsMap result = AnimationStack::activeInterpolations( | |
| 122 &element->elementAnimations()->animationStack(), &newAnimations, 0, | |
| 123 KeyframeEffectReadOnly::DefaultPriority); | |
| 124 EXPECT_EQ(2u, result.size()); | |
| 125 EXPECT_TRUE(interpolationValue(result, CSSPropertyFontSize) | |
| 126 ->equals(AnimatableDouble::create(3).get())); | |
| 127 EXPECT_TRUE(interpolationValue(result, CSSPropertyZIndex) | |
| 128 ->equals(AnimatableDouble::create(4).get())); | |
| 129 } | |
| 130 | |
| 131 TEST_F(AnimationAnimationStackTest, CancelledAnimations) { | |
| 132 HeapHashSet<Member<const Animation>> cancelledAnimations; | |
| 133 Animation* animation = | |
| 134 play(makeKeyframeEffect(makeEffectModel(CSSPropertyFontSize, | |
| 135 AnimatableDouble::create(1))), | |
| 136 0); | |
| 137 cancelledAnimations.add(animation); | |
| 138 play(makeKeyframeEffect( | |
| 139 makeEffectModel(CSSPropertyZIndex, AnimatableDouble::create(2))), | |
| 140 0); | |
| 141 ActiveInterpolationsMap result = AnimationStack::activeInterpolations( | |
| 142 &element->elementAnimations()->animationStack(), 0, &cancelledAnimations, | |
| 143 KeyframeEffectReadOnly::DefaultPriority); | |
| 144 EXPECT_EQ(1u, result.size()); | |
| 145 EXPECT_TRUE(interpolationValue(result, CSSPropertyZIndex) | |
| 146 ->equals(AnimatableDouble::create(2).get())); | |
| 147 } | |
| 148 | |
| 149 TEST_F(AnimationAnimationStackTest, ClearedEffectsRemoved) { | |
| 150 Animation* animation = | |
| 151 play(makeKeyframeEffect(makeEffectModel(CSSPropertyFontSize, | |
| 152 AnimatableDouble::create(1))), | |
| 153 10); | |
| 154 ActiveInterpolationsMap result = AnimationStack::activeInterpolations( | |
| 155 &element->elementAnimations()->animationStack(), 0, 0, | |
| 156 KeyframeEffectReadOnly::DefaultPriority); | |
| 157 EXPECT_EQ(1u, result.size()); | |
| 158 EXPECT_TRUE(interpolationValue(result, CSSPropertyFontSize) | |
| 159 ->equals(AnimatableDouble::create(1).get())); | |
| 160 | |
| 161 animation->setEffect(0); | |
| 162 result = AnimationStack::activeInterpolations( | |
| 163 &element->elementAnimations()->animationStack(), 0, 0, | |
| 164 KeyframeEffectReadOnly::DefaultPriority); | |
| 165 EXPECT_EQ(0u, result.size()); | |
| 166 } | |
| 167 | |
| 168 TEST_F(AnimationAnimationStackTest, ForwardsFillDiscarding) { | |
| 169 play(makeKeyframeEffect( | |
| 170 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(1))), | |
| 171 2); | |
| 172 play(makeKeyframeEffect( | |
| 173 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(2))), | |
| 174 6); | |
| 175 play(makeKeyframeEffect( | |
| 176 makeEffectModel(CSSPropertyFontSize, AnimatableDouble::create(3))), | |
| 177 4); | |
| 178 document->compositorPendingAnimations().update(); | |
| 179 ActiveInterpolationsMap interpolations; | |
| 180 | |
| 181 updateTimeline(11); | |
| 182 ThreadState::current()->collectAllGarbage(); | |
| 183 interpolations = AnimationStack::activeInterpolations( | |
| 184 &element->elementAnimations()->animationStack(), nullptr, nullptr, | |
| 185 KeyframeEffectReadOnly::DefaultPriority); | |
| 186 EXPECT_EQ(1u, interpolations.size()); | |
| 187 EXPECT_TRUE(interpolationValue(interpolations, CSSPropertyFontSize) | |
| 188 ->equals(AnimatableDouble::create(3).get())); | |
| 189 EXPECT_EQ(3u, sampledEffectCount()); | |
| 190 | |
| 191 updateTimeline(13); | |
| 192 ThreadState::current()->collectAllGarbage(); | |
| 193 interpolations = AnimationStack::activeInterpolations( | |
| 194 &element->elementAnimations()->animationStack(), nullptr, nullptr, | |
| 195 KeyframeEffectReadOnly::DefaultPriority); | |
| 196 EXPECT_EQ(1u, interpolations.size()); | |
| 197 EXPECT_TRUE(interpolationValue(interpolations, CSSPropertyFontSize) | |
| 198 ->equals(AnimatableDouble::create(3).get())); | |
| 199 EXPECT_EQ(3u, sampledEffectCount()); | |
| 200 | |
| 201 updateTimeline(15); | |
| 202 ThreadState::current()->collectAllGarbage(); | |
| 203 interpolations = AnimationStack::activeInterpolations( | |
| 204 &element->elementAnimations()->animationStack(), nullptr, nullptr, | |
| 205 KeyframeEffectReadOnly::DefaultPriority); | |
| 206 EXPECT_EQ(1u, interpolations.size()); | |
| 207 EXPECT_TRUE(interpolationValue(interpolations, CSSPropertyFontSize) | |
| 208 ->equals(AnimatableDouble::create(3).get())); | |
| 209 EXPECT_EQ(2u, sampledEffectCount()); | |
| 210 | |
| 211 updateTimeline(17); | |
| 212 ThreadState::current()->collectAllGarbage(); | |
| 213 interpolations = AnimationStack::activeInterpolations( | |
| 214 &element->elementAnimations()->animationStack(), nullptr, nullptr, | |
| 215 KeyframeEffectReadOnly::DefaultPriority); | |
| 216 EXPECT_EQ(1u, interpolations.size()); | |
| 217 EXPECT_TRUE(interpolationValue(interpolations, CSSPropertyFontSize) | |
| 218 ->equals(AnimatableDouble::create(3).get())); | |
| 219 EXPECT_EQ(1u, sampledEffectCount()); | |
| 220 } | |
| 221 | |
| 222 } // namespace blink | |
| OLD | NEW |