Index: Source/core/animation/CompositorAnimations.cpp |
diff --git a/Source/core/animation/CompositorAnimations.cpp b/Source/core/animation/CompositorAnimations.cpp |
index 306e1e709e05e428f5019a6962fdc8055cde9a86..c9acde5af9e0bbae5c74f1de969add6a636ecd63 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)) |
+ CompositorTiming out; |
+ if (!convertTimingForCompositor(timing, out)) |
return false; |
- // FIXME: Support positive startDelay and iterations. |
- if (timing.iterationCount != 1 && timing.startDelay > 0.0) |
- return false; |
- |
- return isCandidateForCompositor(*timing.timingFunction.get(), frames); |
+ 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 && frames->size() == 2))) |
return false; |
- if (frames[0]->offset() - frameOffset) |
- return false; |
+ ASSERT(!frames || (frames->at(0)->offset() == 0.0 && frames->at(1)->offset() == 1.0)); |
return true; |
@@ -284,26 +261,22 @@ 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()) |
return false; |
- if (frames.size() != chained->m_segments.size() + 1) |
+ if (frames->size() != chained->m_segments.size() + 1) |
return false; |
for (size_t timeIndex = 0; timeIndex < chained->m_segments.size(); timeIndex++) { |
const ChainedTimingFunction::Segment& segment = chained->m_segments[timeIndex]; |
- if (frames[timeIndex]->offset() != segment.m_min || frames[timeIndex + 1]->offset() != segment.m_max) |
+ if (frames->at(timeIndex)->offset() != segment.m_min || frames->at(timeIndex + 1)->offset() != segment.m_max) |
return false; |
- KeyframeAnimationEffect::KeyframeVector timingFrames; |
- 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(), 0, true)) |
return false; |
} |
return true; |
@@ -314,6 +287,60 @@ bool CompositorAnimationsImpl::isCandidateForCompositor(const TimingFunction& ti |
return false; |
} |
+bool CompositorAnimationsImpl::convertTimingForCompositor(const Timing& timing, CompositorTiming& out) |
+{ |
+ timing.assertValid(); |
+ |
+ // 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) |
+ return false; |
+ |
+ // FIXME: Compositor only supports finite, non-zero, integer iteration |
+ // counts. |
+ if (!std::isfinite(timing.iterationCount) || (std::floor(timing.iterationCount) != timing.iterationCount) || !timing.iterationCount) |
+ return false; |
+ |
+ if (!timing.iterationDuration) |
+ return false; |
+ |
+ // FIXME: Support other playback rates |
+ if (timing.playbackRate != 1) |
+ return false; |
+ |
+ // All directions are supported. |
+ |
+ // Now attempt an actual conversion |
+ out.scaledDuration = timing.iterationDuration; |
+ ASSERT(out.scaledDuration > 0); |
+ |
+ double scaledStartDelay = timing.startDelay; |
+ ASSERT(scaledStartDelay <= 0); |
+ |
+ int skippedIterations = std::floor(std::abs(scaledStartDelay) / out.scaledDuration); |
+ ASSERT(skippedIterations >= 0); |
+ if (skippedIterations >= timing.iterationCount) |
+ return false; |
+ |
+ out.reverse = (timing.direction == Timing::PlaybackDirectionReverse |
+ || timing.direction == Timing::PlaybackDirectionAlternateReverse); |
+ out.alternate = (timing.direction == Timing::PlaybackDirectionAlternate |
+ || timing.direction == Timing::PlaybackDirectionAlternateReverse); |
+ if (out.alternate && (skippedIterations % 2)) |
+ out.reverse = !out.reverse; |
+ |
+ out.adjustedIterationCount = std::floor(timing.iterationCount) - skippedIterations; |
+ ASSERT(out.adjustedIterationCount > 0); |
+ |
+ out.scaledTimeOffset = scaledStartDelay + skippedIterations * 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_UNUSED(timingValid, timingValid); |
RefPtr<TimingFunction> timingFunction = timing.timingFunction; |
- if (reverse) { |
+ if (compositorTiming.reverse) |
timingFunction = CompositorAnimationsTimingFunctionReverser::reverse(timingFunction.get()); |
- } |
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()); |
} |