1 /* 2 * Copyright (C) 2013 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/animation/AnimationNode.h" 33 34 #include "core/animation/AnimationNodeTiming.h" 35 #include "core/animation/AnimationPlayer.h" 36 #include "core/animation/TimingCalculations.h" 37 38 namespace blink { 39 40 namespace { 41 42 Timing::FillMode resolvedFillMode(Timing::FillMode fillMode, bool isAnimation) 43 { 44 if (fillMode != Timing::FillModeAuto) 45 return fillMode; 46 if (isAnimation) 47 return Timing::FillModeNone; 48 return Timing::FillModeBoth; 49 } 50 51 } // namespace 52 53 AnimationNode::AnimationNode(const Timing& timing, PassOwnPtrWillBeRawPtr<EventDelegate> eventDelegate) 54 : m_parent(nullptr) 55 , m_startTime(0) 56 , m_player(nullptr) 57 , m_timing(timing) 58 , m_eventDelegate(eventDelegate) 59 , m_calculated() 60 , m_needsUpdate(true) 61 , m_lastUpdateTime(nullValue()) 62 { 63 m_timing.assertValid(); 64 } 65 66 double AnimationNode::iterationDuration() const 67 { 68 double result = std::isnan(m_timing.iterationDuration) ? intrinsicIterationDuration() : m_timing.iterationDuration; 69 ASSERT(result >= 0); 70 return result; 71 } 72 73 double AnimationNode::repeatedDuration() const 74 { 75 const double result = multiplyZeroAlwaysGivesZero(iterationDuration(), m_timing.iterationCount); 76 ASSERT(result >= 0); 77 return result; 78 } 79 80 double AnimationNode::activeDurationInternal() const 81 { 82 const double result = m_timing.playbackRate 83 ? repeatedDuration() / std::abs(m_timing.playbackRate) 84 : std::numeric_limits<double>::infinity(); 85 ASSERT(result >= 0); 86 return result; 87 } 88 89 void AnimationNode::updateSpecifiedTiming(const Timing& timing) 90 { 91 // FIXME: Test whether the timing is actually different? 92 m_timing = timing; 93 invalidate(); 94 if (m_player) 95 m_player->setOutdated(); 96 specifiedTimingChanged(); 97 } 98 99 void AnimationNode::updateInheritedTime(double inheritedTime, TimingUpdateReason reason) const 100 { 101 bool needsUpdate = m_needsUpdate || (m_lastUpdateTime != inheritedTime && !(isNull(m_lastUpdateTime) && isNull(inheritedTime))); 102 m_needsUpdate = false; 103 m_lastUpdateTime = inheritedTime; 104 105 const double localTime = inheritedTime - m_startTime; 106 double timeToNextIteration = std::numeric_limits<double>::infinity(); 107 if (needsUpdate) { 108 const double activeDuration = this->activeDurationInternal(); 109 110 const Phase currentPhase = calculatePhase(activeDuration, localTime, m_timing); 111 // FIXME: parentPhase depends on groups being implemented. 112 const AnimationNode::Phase parentPhase = AnimationNode::PhaseActive; 113 const double activeTime = calculateActiveTime(activeDuration, resolvedFillMode(m_timing.fillMode, isAnimation()), localTime, parentPhase, currentPhase, m_timing); 114 115 double currentIteration; 116 double timeFraction; 117 if (const double iterationDuration = this->iterationDuration()) { 118 const double startOffset = multiplyZeroAlwaysGivesZero(m_timing.iterationStart, iterationDuration); 119 ASSERT(startOffset >= 0); 120 const double scaledActiveTime = calculateScaledActiveTime(activeDuration, activeTime, startOffset, m_timing); 121 const double iterationTime = calculateIterationTime(iterationDuration, repeatedDuration(), scaledActiveTime, startOffset, m_timing); 122 123 currentIteration = calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, m_timing); 124 timeFraction = calculateTransformedTime(currentIteration, iterationDuration, iterationTime, m_timing) / iterationDuration; 125 126 if (!isNull(iterationTime)) { 127 timeToNextIteration = (iterationDuration - iterationTime) / std::abs(m_timing.playbackRate); 128 if (activeDuration - activeTime < timeToNextIteration) 129 timeToNextIteration = std::numeric_limits<double>::infinity(); 130 } 131 } else { 132 const double localIterationDuration = 1; 133 const double localRepeatedDuration = localIterationDuration * m_timing.iterationCount; 134 ASSERT(localRepeatedDuration >= 0); 135 const double localActiveDuration = m_timing.playbackRate ? localRepeatedDuration / std::abs(m_timing.playbackRate) : std::numeric_limits<double>::infinity(); 136 ASSERT(localActiveDuration >= 0); 137 const double localLocalTime = localTime < m_timing.startDelay ? localTime : localActiveDuration + m_timing.startDelay; 138 const AnimationNode::Phase localCurrentPhase = calculatePhase(localActiveDuration, localLocalTime, m_timing); 139 const double localActiveTime = calculateActiveTime(localActiveDuration, resolvedFillMode(m_timing.fillMode, isAnimation()), localLocalTime, parentPhase, localCurrentPhase, m_timing); 140 const double startOffset = m_timing.iterationStart * localIterationDuration; 141 ASSERT(startOffset >= 0); 142 const double scaledActiveTime = calculateScaledActiveTime(localActiveDuration, localActiveTime, startOffset, m_timing); 143 const double iterationTime = calculateIterationTime(localIterationDuration, localRepeatedDuration, scaledActiveTime, startOffset, m_timing); 144 145 currentIteration = calculateCurrentIteration(localIterationDuration, iterationTime, scaledActiveTime, m_timing); 146 timeFraction = calculateTransformedTime(currentIteration, localIterationDuration, iterationTime, m_timing); 147 } 148 149 m_calculated.currentIteration = currentIteration; 150 m_calculated.timeFraction = timeFraction; 151 152 m_calculated.phase = currentPhase; 153 m_calculated.isInEffect = !isNull(activeTime); 154 m_calculated.isInPlay = phase() == PhaseActive && (!m_parent || m_parent->isInPlay()); 155 m_calculated.isCurrent = phase() == PhaseBefore || isInPlay() || (m_parent && m_parent->isCurrent()); 156 m_calculated.localTime = m_lastUpdateTime - m_startTime; 157 } 158 159 // Test for events even if timing didn't need an update as the player may have gained a start time. 160 // FIXME: Refactor so that we can ASSERT(m_player) here, this is currently required to be nullable for testing. 161 if (reason == TimingUpdateForAnimationFrame && (!m_player || m_player->hasStartTime() || m_player->paused())) { 162 if (m_eventDelegate) 163 m_eventDelegate->onEventCondition(this); 164 } 165 166 if (needsUpdate) { 167 // FIXME: This probably shouldn't be recursive. 168 updateChildrenAndEffects(); 169 m_calculated.timeToForwardsEffectChange = calculateTimeToEffectChange(true, localTime, timeToNextIteration); 170 m_calculated.timeToReverseEffectChange = calculateTimeToEffectChange(false, localTime, timeToNextIteration); 171 } 172 } 173 174 const AnimationNode::CalculatedTiming& AnimationNode::ensureCalculated() const 175 { 176 if (!m_player) 177 return m_calculated; 178 if (m_player->outdated()) 179 m_player->update(TimingUpdateOnDemand); 180 ASSERT(!m_player->outdated()); 181 return m_calculated; 182 } 183 184 PassRefPtrWillBeRawPtr<AnimationNodeTiming> AnimationNode::timing() 185 { 186 return AnimationNodeTiming::create(this); 187 } 188 189 void AnimationNode::trace(Visitor* visitor) 190 { 191 visitor->trace(m_parent); 192 visitor->trace(m_player); 193 visitor->trace(m_eventDelegate); 194 } 195 196 } // namespace blink 197