Chromium Code Reviews| Index: Source/core/animation/CompositorAnimations.cpp |
| diff --git a/Source/core/animation/CompositorAnimations.cpp b/Source/core/animation/CompositorAnimations.cpp |
| index 306e1e709e05e428f5019a6962fdc8055cde9a86..0f34659737234d2d8c96db8f34c3517fe358b990 100644 |
| --- a/Source/core/animation/CompositorAnimations.cpp |
| +++ b/Source/core/animation/CompositorAnimations.cpp |
| @@ -43,17 +43,12 @@ |
| #include "public/platform/Platform.h" |
| #include "public/platform/WebAnimation.h" |
| #include "public/platform/WebCompositorSupport.h" |
| -#include "public/platform/WebFilterAnimationCurve.h" |
| #include "public/platform/WebFloatAnimationCurve.h" |
| #include "public/platform/WebFloatKeyframe.h" |
| -#include "public/platform/WebTransformAnimationCurve.h" |
| -#include "public/platform/WebTransformKeyframe.h" |
| -#include "public/platform/WebTransformOperations.h" |
| #include <algorithm> |
| #include <cmath> |
| - |
| namespace WebCore { |
| // ----------------------------------------------------------------------- |
| @@ -174,14 +169,14 @@ PassOwnPtr<Vector<CSSPropertyID> > CompositorAnimationsKeyframeEffectHelper::get |
| } |
| PassOwnPtr<CompositorAnimationsKeyframeEffectHelper::KeyframeValues> CompositorAnimationsKeyframeEffectHelper::getKeyframeValuesForProperty( |
| - const KeyframeAnimationEffect* effect, CSSPropertyID id, double zero, double scale, bool reverse) |
| + const KeyframeAnimationEffect* effect, CSSPropertyID id, double scale, bool reverse) |
| { |
| const_cast<KeyframeAnimationEffect*>(effect)->ensureKeyframeGroups(); |
| - return getKeyframeValuesForProperty(effect->m_keyframeGroups->get(id), zero, scale, reverse); |
| + return getKeyframeValuesForProperty(effect->m_keyframeGroups->get(id), scale, reverse); |
| } |
| PassOwnPtr<CompositorAnimationsKeyframeEffectHelper::KeyframeValues> CompositorAnimationsKeyframeEffectHelper::getKeyframeValuesForProperty( |
| - const KeyframeAnimationEffect::PropertySpecificKeyframeGroup* group, double zero, double scale, bool reverse) |
| + const KeyframeAnimationEffect::PropertySpecificKeyframeGroup* group, double scale, bool reverse) |
| { |
| OwnPtr<CompositorAnimationsKeyframeEffectHelper::KeyframeValues> values = adoptPtr( |
| new CompositorAnimationsKeyframeEffectHelper::KeyframeValues()); |
| @@ -189,10 +184,7 @@ PassOwnPtr<CompositorAnimationsKeyframeEffectHelper::KeyframeValues> CompositorA |
| for (size_t i = 0; i < group->m_keyframes.size(); i++) { |
| KeyframeAnimationEffect::PropertySpecificKeyframe* frame = group->m_keyframes[i].get(); |
| - double offset = zero + frame->offset() * scale; |
| - if (reverse) |
| - offset = zero + (1 - frame->offset()) * scale; |
| - |
| + double offset = (reverse ? (1 - frame->offset()) : frame->offset()) * scale; |
| values->append(std::make_pair(offset, frame->value())); |
| } |
| if (reverse) |
| @@ -218,7 +210,7 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const Keyframe& keyframe |
| case CSSPropertyOpacity: |
| case CSSPropertyWebkitFilter: // FIXME: What about CSSPropertyFilter? |
| case CSSPropertyWebkitTransform: |
| - return true; |
| + continue; |
| default: |
| return false; |
| } |
| @@ -238,29 +230,15 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const KeyframeAnimationE |
| bool CompositorAnimationsImpl::isCandidateForCompositor(const Timing& timing, const KeyframeAnimationEffect::KeyframeVector& frames) |
| { |
| - // FIXME: Support more then FillModeNone. |
| - if (timing.fillMode != Timing::FillModeNone) |
| - return false; |
| - |
| - if (!timing.hasIterationDuration) |
| - return false; |
| - |
| - // FIXME: Support non-zero iteration start. |
| - if (timing.iterationStart != 0.0) |
| - return false; |
| - |
| - // FIXME: Compositor only supports integer iteration counts. |
| - if (!std::isfinite(timing.iterationCount) || (timing.iterationCount < 0) || (std::floor(timing.iterationCount) != timing.iterationCount)) |
| - return false; |
| - // FIXME: Support positive startDelay and iterations. |
| - if (timing.iterationCount != 1 && timing.startDelay > 0.0) |
| + CompositorTiming out; |
| + if (!convertTimingForCompositor(timing, out)) |
| return false; |
| return isCandidateForCompositor(*timing.timingFunction.get(), frames); |
| } |
| -bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& timingFunction, const KeyframeAnimationEffect::KeyframeVector& frames, double frameOffset) |
| +bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& timingFunction, const KeyframeAnimationEffect::KeyframeVector& frames, bool isNestedCall) |
| { |
| switch (timingFunction.type()) { |
| case TimingFunction::LinearFunction: |
| @@ -268,11 +246,10 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& ti |
| case TimingFunction::CubicBezierFunction: |
| // Can have a cubic if we don't have to split it (IE only have two frames). |
| - if (frames.size() != 2) |
| + if (!isNestedCall && (frames.size() != 2)) |
| return false; |
| - if (frames[0]->offset() - frameOffset) |
| - return false; |
| + ASSERT(!frames.size() || (frames[0]->offset() == 0.0 && frames[1]->offset() == 1.0)); |
| return true; |
| @@ -284,7 +261,7 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& ti |
| // generates. These chained segments are only one level deep and have |
| // one timing function per frame. |
| const ChainedTimingFunction* chained = static_cast<const ChainedTimingFunction*>(&timingFunction); |
| - if (frameOffset) |
| + if (isNestedCall) |
| return false; |
| if (!chained->m_segments.size()) |
| @@ -300,10 +277,7 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& ti |
| return false; |
| KeyframeAnimationEffect::KeyframeVector timingFrames; |
|
Steve Block
2013/11/13 23:17:01
Yes, I think we should convert this function to ta
mithro-old
2013/11/14 02:11:46
Done.
|
| - timingFrames.append(frames[timeIndex]); |
| - timingFrames.append(frames[timeIndex + 1]); |
| - |
| - if (!isCandidateForCompositor(*(segment.m_timingFunction.get()), timingFrames, segment.m_min)) |
| + if (!isCandidateForCompositor(*segment.m_timingFunction.get(), timingFrames, true)) |
| return false; |
| } |
| return true; |
| @@ -314,6 +288,59 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& ti |
| return false; |
| } |
| +bool CompositorAnimationsImpl::convertTimingForCompositor(const Timing& timing, CompositorTiming& out) |
| +{ |
| + timing.assertValid(); |
| + // FIXME: Shouldn't this be asserted in timing.assertValid? |
|
Steve Block
2013/11/13 23:17:01
Good question. It should always be true right now,
mithro-old
2013/11/14 02:11:46
Done.
|
| + ASSERT(timing.timingFunction); |
| + |
| + // FIXME: Support positive startDelay |
| + if (timing.startDelay > 0.0) |
| + return false; |
| + |
| + // All fill modes are supported (the calling code handles them). |
| + |
| + // FIXME: Support non-zero iteration start. |
| + if (timing.iterationStart != 0.0) |
|
Steve Block
2013/11/13 23:17:01
if (timing.iterationStart)
Ugly I know, but that'
mithro-old
2013/11/14 02:11:46
Done.
Normally the style checker picks this up, w
|
| + return false; |
| + |
| + // FIXME: Compositor only supports finite, integer iteration counts. |
| + if (!std::isfinite(timing.iterationCount) || (std::floor(timing.iterationCount) != timing.iterationCount)) |
| + return false; |
| + |
| + if (!timing.iterationDuration) |
| + return false; |
| + |
| + if (timing.playbackRate <= 0) |
|
Steve Block
2013/11/13 23:17:01
Why doesn't this one get a FIXME?
mithro-old
2013/11/14 02:11:46
Does now! Changed to == 1.0 as Doug requested.
|
| + return false; |
| + |
| + // All directions are supported. |
| + out.reverse = (timing.direction == Timing::PlaybackDirectionReverse |
| + || timing.direction == Timing::PlaybackDirectionAlternateReverse); |
| + out.alternate = (timing.direction == Timing::PlaybackDirectionAlternate |
| + || timing.direction == Timing::PlaybackDirectionAlternateReverse); |
|
Steve Block
2013/11/13 23:17:01
Move these down to line 334 where they're used, to
mithro-old
2013/11/14 02:11:46
Done.
|
| + |
| + out.scaledDuration = timing.iterationDuration / timing.playbackRate; |
|
dstockwell
2013/11/13 11:54:04
I think we should just bail out if playbackRate is
mithro-old
2013/11/13 12:01:43
Trivial to implement, but can remove it you want.
dstockwell
2013/11/13 23:29:31
Remove it.
mithro-old
2013/11/14 02:11:46
Done.
|
| + ASSERT(out.scaledDuration > 0); |
| + |
| + double scaledStartDelay = timing.startDelay / timing.playbackRate; |
| + ASSERT(scaledStartDelay <= 0); |
| + |
| + int pastIterations = std::floor(std::abs(scaledStartDelay) / out.scaledDuration); |
|
dstockwell
2013/11/13 11:54:04
It's not really clear to me what's going on here.
mithro-old
2013/11/13 12:01:43
When start delay greater than iteration duration m
dstockwell
2013/11/13 23:29:31
OK. Then I think something like skippedIterations
mithro-old
2013/11/14 02:11:46
Done.
|
| + ASSERT(pastIterations >= 0); |
| + if (pastIterations >= timing.iterationCount) |
| + return false; |
| + |
| + if (out.alternate && (pastIterations % 2)) |
| + out.reverse = !out.reverse; |
| + |
| + out.adjustedIterationCount = std::floor(timing.iterationCount) - pastIterations; |
| + ASSERT(out.adjustedIterationCount > 0); |
|
Steve Block
2013/11/13 23:17:01
What if timing.iterationCount is zero?
For exampl
dstockwell
2013/11/13 23:29:31
Right, bail out if iteration count is 0.
mithro-old
2013/11/14 02:11:46
Actually we'd bail at line 331, in the zero case s
Steve Block
2013/11/14 02:28:08
Sounds good. This will be required once we allow p
|
| + |
| + out.scaledTimeOffset = scaledStartDelay + pastIterations * out.scaledDuration; |
| + ASSERT(out.scaledTimeOffset <= 0); |
| + return true; |
| +} |
| namespace { |
| @@ -407,7 +434,7 @@ void CompositorAnimationsImpl::addKeyframesToCurve(PlatformAnimationCurveType& c |
| const ChainedTimingFunction* chained = static_cast<const ChainedTimingFunction*>(&timingFunction); |
| // ChainedTimingFunction criteria was checked in isCandidate, |
| // assert it is valid. |
| - ASSERT(values.size() == chained->m_segments.size()+1); |
| + ASSERT(values.size() == chained->m_segments.size() + 1); |
| ASSERT(values[i].first == chained->m_segments[i].m_min); |
| keyframeTimingFunction = chained->m_segments[i].m_timingFunction.get(); |
| @@ -429,24 +456,19 @@ void CompositorAnimationsImpl::addKeyframesToCurve(PlatformAnimationCurveType& c |
| void CompositorAnimationsImpl::getCompositorAnimations( |
| const Timing& timing, const KeyframeAnimationEffect& effect, Vector<OwnPtr<blink::WebAnimation> >& animations) |
| { |
| - |
| - bool reverse = (timing.direction == Timing::PlaybackDirectionReverse |
| - || timing.direction == Timing::PlaybackDirectionAlternateReverse); |
| + CompositorTiming compositorTiming; |
| + bool timingValid = convertTimingForCompositor(timing, compositorTiming); |
| + ASSERT(timingValid); |
|
Steve Block
2013/11/13 23:17:01
I think this will need to be an ASSERT_UNUSED for
mithro-old
2013/11/14 02:11:46
Done.
|
| RefPtr<TimingFunction> timingFunction = timing.timingFunction; |
| - if (reverse) { |
| + if (compositorTiming.reverse) |
| timingFunction = CompositorAnimationsTimingFunctionReverser::reverse(timingFunction.get()); |
|
dstockwell
2013/11/13 23:29:31
Hmm, why do we need to reverse the timing function
dstockwell
2013/11/13 23:41:05
Probably because reverse isn't passed through. Som
Steve Block
2013/11/13 23:56:23
That's my understanding too. The compositor interf
mithro-old
2013/11/14 02:11:46
Correct. If we could just pass reverse, life would
mithro-old
2013/11/14 02:11:46
Correct.
mithro-old
2013/11/14 02:11:46
Because it's not passed to the compositor.
To sim
|
| - } |
| OwnPtr<Vector<CSSPropertyID> > properties = CompositorAnimationsKeyframeEffectHelper::getProperties(&effect); |
| for (size_t i = 0; i < properties->size(); i++) { |
| - double iterationDuration = timing.iterationDuration / timing.playbackRate; |
| - |
| - double zero = timing.startDelay / timing.playbackRate; |
| - double keyframeZero = std::max(0.0, zero); |
| OwnPtr<CompositorAnimationsKeyframeEffectHelper::KeyframeValues> values = CompositorAnimationsKeyframeEffectHelper::getKeyframeValuesForProperty( |
| - &effect, properties->at(i), keyframeZero, iterationDuration, reverse); |
| + &effect, properties->at(i), compositorTiming.scaledDuration, compositorTiming.reverse); |
| blink::WebAnimation::TargetProperty targetProperty; |
| OwnPtr<blink::WebAnimationCurve> curve; |
| @@ -479,20 +501,9 @@ void CompositorAnimationsImpl::getCompositorAnimations( |
| OwnPtr<blink::WebAnimation> animation = adoptPtr( |
| blink::Platform::current()->compositorSupport()->createAnimation(*curve, targetProperty)); |
| - ASSERT(std::floor(timing.iterationCount) == timing.iterationCount); |
| - ASSERT(std::isfinite(timing.iterationCount)); |
| - double iterationCount = std::floor(timing.iterationCount); |
| - if (zero < 0) { |
| - int pastIterations = std::floor(std::abs(zero) / iterationDuration); |
| - |
| - iterationCount = iterationCount - pastIterations; |
| - animation->setTimeOffset(zero + pastIterations * iterationDuration); |
| - } |
| - animation->setIterations(iterationCount); |
| - |
| - // PlaybackDirection direction |
| - animation->setAlternatesDirection( |
| - timing.direction == Timing::PlaybackDirectionAlternate || timing.direction == Timing::PlaybackDirectionAlternateReverse); |
| + animation->setIterations(compositorTiming.adjustedIterationCount); |
| + animation->setTimeOffset(compositorTiming.scaledTimeOffset); |
| + animation->setAlternatesDirection(compositorTiming.alternate); |
| animations.append(animation.release()); |
| } |