Chromium Code Reviews| Index: Source/core/animation/ElementAnimation.cpp |
| diff --git a/Source/core/animation/ElementAnimation.cpp b/Source/core/animation/ElementAnimation.cpp |
| index f3c109e298d8976ed1abacd9c3fae3d8a5518f6c..76c3eecbda26e4c7981138708aa7b1824f6aa25f 100644 |
| --- a/Source/core/animation/ElementAnimation.cpp |
| +++ b/Source/core/animation/ElementAnimation.cpp |
| @@ -31,6 +31,7 @@ |
| #include "config.h" |
| #include "core/animation/ElementAnimation.h" |
| +#include "bindings/v8/ScriptValue.h" |
| #include "core/animation/DocumentTimeline.h" |
| #include "core/css/RuntimeCSSEnabled.h" |
| #include "core/css/resolver/StyleResolver.h" |
| @@ -66,22 +67,120 @@ CSSPropertyID ElementAnimation::camelCaseCSSPropertyNameToID(StringImpl* propert |
| return id; |
| } |
| -void ElementAnimation::animate(Element* element, Vector<Dictionary> keyframeDictionaryVector, double duration) |
| +static bool populateTiming(Timing& timing, Dictionary timingInputDictionary) |
| +{ |
| + if (timingInputDictionary.hasProperty("startDelay")) { |
|
Steve Block
2013/12/17 00:05:35
This has been renamed to 'delay'. We should rename
rjwright
2013/12/18 04:17:14
Ok. Is it just this one? And is the spec up to dat
|
| + double startDelay = std::numeric_limits<double>::quiet_NaN(); |
| + timingInputDictionary.get("startDelay", startDelay); |
| + ASSERT(!isnan(startDelay)); |
| + ASSERT(!isinf(startDelay)); |
|
Steve Block
2013/12/17 00:05:35
We shouldn't be asserting here - a developer could
rjwright
2013/12/18 04:17:14
Done.
|
| + if (isnan(startDelay) || isinf(startDelay)) |
| + return false; |
| + timing.startDelay = startDelay; |
| + } |
|
shans
2013/12/16 23:47:22
I think it's simpler to check the bool result of D
rjwright1
2013/12/16 23:58:31
Ok,but these two suggestions only work in unison.
rjwright
2013/12/18 04:17:14
Done.
|
| + |
| + if (timingInputDictionary.hasProperty("fillMode")) { |
| + String fillMode; |
| + timingInputDictionary.get("fillMode", fillMode); |
| + |
| + if (fillMode == "none") { |
| + timing.fillMode = Timing::FillModeNone; |
| + } else if (fillMode == "forwards") { |
| + timing.fillMode = Timing::FillModeForwards; |
| + } else if (fillMode == "backwards") { |
| + timing.fillMode = Timing::FillModeBackwards; |
| + } else if (fillMode == "both") { |
| + timing.fillMode = Timing::FillModeBoth; |
| + } else { |
| + ASSERT_NOT_REACHED(); |
|
Steve Block
2013/12/17 00:05:35
Same thing about asserting and ignoring invalid in
rjwright
2013/12/18 04:17:14
Done.
|
| + return false; |
| + } |
| + } |
| + |
| + if (timingInputDictionary.hasProperty("iterationStart")) { |
| + double iterationStart = std::numeric_limits<double>::quiet_NaN(); |
| + timingInputDictionary.get("iterationStart", iterationStart); |
| + ASSERT(!isnan(iterationStart)); |
| + ASSERT(!isinf(iterationStart)); |
| + if (isnan(iterationStart) || isinf(iterationStart)) |
| + return false; |
| + timing.iterationStart = std::max<double>(iterationStart, 0); |
| + } |
| + |
| + if (timingInputDictionary.hasProperty("iterationCount")) { |
| + double iterationCount = std::numeric_limits<double>::quiet_NaN(); |
| + timingInputDictionary.get("iterationCount", iterationCount); |
| + ASSERT(!isnan(iterationCount)); |
| + if (isnan(iterationCount)) |
| + return false; |
| + timing.iterationCount = std::max<double>(iterationCount, 0); |
| + } |
| + |
| + if (timingInputDictionary.hasProperty("iterationDuration")) { |
| + v8::Local<v8::Value> iterationDurationValue; |
| + timingInputDictionary.get("iterationDuration", iterationDurationValue); |
| + |
| + double iterationDuration; |
| + if (iterationDurationValue->IsString()) { |
| + // All strings are treated as 'auto' except strings that are numbers, e.g. '1' |
| + bool isDouble = true; |
| + iterationDuration = toCoreString(iterationDurationValue->ToString()).toDouble(&isDouble); |
| + if (isDouble) |
| + timing.iterationDuration = std::max<double>(iterationDuration, 0); |
| + else |
| + timing.iterationDuration = 0; |
| + timing.hasIterationDuration = true; |
| + } else if (iterationDurationValue->IsNumber()) { |
| + iterationDuration = iterationDurationValue->NumberValue(); |
| + ASSERT(!isnan(iterationDuration)); |
| + if (isnan(iterationDuration)) |
| + return false; |
| + timing.iterationDuration = std::max<double>(iterationDuration, 0); |
| + timing.hasIterationDuration = true; |
| + } else { |
| + ASSERT_NOT_REACHED(); |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +static bool checkDocumentAndRenderer(Element* element) |
| +{ |
| + if (!element->inActiveDocument()) |
| + return false; |
| + element->document().updateStyleIfNeeded(); |
| + if (!element->renderer()) |
| + return false; |
| + return true; |
| +} |
| + |
| +void ElementAnimation::animate(Element* element, Vector<Dictionary> keyframeDictionaryVector) |
| { |
| ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled()); |
| // FIXME: This test will not be neccessary once resolution of keyframe values occurs at |
| // animation application time. |
| - if (!element->inActiveDocument()) |
| + if (!checkDocumentAndRenderer(element)) |
| return; |
| - element->document().updateStyleIfNeeded(); |
| - if (!element->renderer()) |
| + |
| + startAnimation(element, keyframeDictionaryVector); |
| +} |
| + |
| +void ElementAnimation::animate(Element* element, Vector<Dictionary> keyframeDictionaryVector, ScriptValue timingInput) |
| +{ |
| + ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled()); |
| + |
| + // FIXME: This test will not be neccessary once resolution of keyframe values occurs at |
| + // animation application time. |
| + if (!checkDocumentAndRenderer(element)) |
| return; |
| - startAnimation(element, keyframeDictionaryVector, duration); |
| + startAnimation(element, keyframeDictionaryVector, timingInput.v8Value()); |
| } |
| -void ElementAnimation::startAnimation(Element* element, Vector<Dictionary> keyframeDictionaryVector, double duration) |
| +void ElementAnimation::startAnimation(Element* element, Vector<Dictionary> keyframeDictionaryVector, v8::Handle<v8::Value> timingInput) |
| { |
| KeyframeAnimationEffect::KeyframeVector keyframes; |
| Vector<RefPtr<MutableStylePropertySet> > propertySetVector; |
| @@ -133,14 +232,20 @@ void ElementAnimation::startAnimation(Element* element, Vector<Dictionary> keyfr |
| // FIXME: Replace this with code that just parses, when that code is available. |
| RefPtr<KeyframeAnimationEffect> effect = StyleResolver::createKeyframeAnimationEffect(*element, propertySetVector, keyframes); |
| - // FIXME: Totally hardcoded Timing for now. Will handle timing parameters later. |
| Timing timing; |
| - // FIXME: Currently there is no way to tell whether or not an iterationDuration |
| - // has been specified (becauser the default argument is 0). So any animation |
| - // created using Element.animate() will have a timing with hasIterationDuration() |
| - // == true. |
| - timing.hasIterationDuration = true; |
| - timing.iterationDuration = std::max<double>(duration, 0); |
| + if (!timingInput.IsEmpty()) { |
| + if (timingInput->IsNumber()) { |
| + timing.hasIterationDuration = true; |
| + timing.iterationDuration = std::max<double>(timingInput->NumberValue(), 0); |
| + } else if (timingInput->IsObject()) { |
| + // FIXME: This just returns if any of the timing input members are invalid |
| + // (e.g. a non-numeric iterationCount). Maybe it should do something more useful. |
| + if (!populateTiming(timing, Dictionary::Dictionary(v8::Handle<v8::Value>::Cast(timingInput), v8::Isolate::GetCurrent()))) |
| + return; |
|
Steve Block
2013/12/17 00:05:35
Again, I don't think we should fail.
rjwright
2013/12/18 04:17:14
Done.
|
| + } else { |
| + return; |
|
Steve Block
2013/12/17 00:05:35
This seems wrong. I think that if timingInput is n
rjwright
2013/12/18 04:17:14
Sounds good, but I have no idea how to do it.
|
| + } |
| + } |
| RefPtr<Animation> animation = Animation::create(element, effect, timing); |
| DocumentTimeline* timeline = element->document().timeline(); |