2010-08-29 Simon Fraser <simon.fraser@apple.com>

        Reviewed by Darin Adler.

        When properties are missing from animation keyframes, interpolate between those keyframes that specify them
        https://bugs.webkit.org/show_bug.cgi?id=40794

        When a property does not appear in all keyframes of a keyframe animation, we currently use the
        value of that property from the unanimated style. That forces the author to use additional
        keyframes for properties that need to "skip a keyframe", which is laborious.

        With this change, properties are interpolated between the keyframes in which they appear.
        This is equivalent to splitting each property out into its own set of keyframes.

        Tests: animations/missing-keyframe-properties-repeating.html
               animations/missing-keyframe-properties-timing-function.html
               animations/missing-keyframe-properties.html

        * css/CSSStyleSelector.h:
        * css/CSSStyleSelector.cpp:
        (WebCore::CSSStyleSelector::styleForKeyframe): Pass a KeyframeValue in so that we can
        collect which properties are represented per keyframe.
        (WebCore::CSSStyleSelector::keyframeStylesForAnimation): Keyframes are inserted into a
        KeyframeList by object now, rather than by key and style.

        * page/animation/AnimationBase.cpp:
        (WebCore::AnimationBase::progress): Use AnimationDirectionAlternate for readability.

        * page/animation/KeyframeAnimation.cpp:
        (WebCore::KeyframeAnimation::fetchIntervalEndpointsForProperty): Renamed from getKeyframeAnimationInterval.
        Use fractionalTime etc to match AnimationBase::progress(), and do lookups per-property.
        Simplify the code that finds the relevant keyframe to do less work.
        (WebCore::KeyframeAnimation::animate): Call fetchIntervalEndpointsForProperty() for each property, rather than just once for the
        entire keyframe.
        (WebCore::KeyframeAnimation::getAnimatedStyle): Ditto.
        (WebCore::KeyframeAnimation::hasAnimationForProperty): FIXME comment.

        * page/animation/KeyframeAnimation.h: Rename getKeyframeAnimationInterval() to fetchIntervalEndpointsForProperty().

        * rendering/RenderLayerBacking.cpp:
        (WebCore::RenderLayerBacking::startAnimation): For hardware animations, only insert values
        for keyframes which contain the property.

        (WebCore::KeyframeList::KeyframeList): insert() takes a KeyframeValue now.
        * rendering/style/KeyframeList.cpp:
        (WebCore::KeyframeList::operator==):
        (WebCore::KeyframeList::insert): Fix insert/replace logic, and ensure we maintain the
        m_properties hash.

        * rendering/style/KeyframeList.h:
        (WebCore::KeyframeValue::KeyframeValue): Make members private, with accessors.
        Add a m_properties HashSet for the properties animated in this keyframe.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66339 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9ed15db2
2010-08-29 Simon Fraser <simon.fraser@apple.com>
Reviewed by Darin Adler.
When properties are missing from animation keyframes, interpolate between those keyframes that specify them
https://bugs.webkit.org/show_bug.cgi?id=40794
Testcases for keyframes with missing properties; repeating and non-repeating.
* animations/missing-from-to-transforms.html:
* animations/missing-from-to.html:
* animations/missing-keyframe-properties-expected.txt: Added.
* animations/missing-keyframe-properties-repeating-expected.txt: Added.
* animations/missing-keyframe-properties-repeating.html: Added.
* animations/missing-keyframe-properties-timing-function-expected.txt: Added.
* animations/missing-keyframe-properties-timing-function.html: Added.
* animations/missing-keyframe-properties.html: Added.
2010-08-28 Darin Adler <darin@apple.com>
Reviewed by Sam Weinig.
......@@ -89,7 +89,7 @@
];
runAnimationTest(expectedValues, function() {
if (layoutTestController) {
if (window.layoutTestController) {
if (layoutTestController.pauseAnimationAtTimeOnElementWithId("anim5", 0.1, "box5"))
result += "FAIL - box5 animation was running<br>";
else
......
......@@ -88,7 +88,7 @@
];
runAnimationTest(expectedValues, function() {
if (layoutTestController) {
if (window.layoutTestController) {
if (layoutTestController.pauseAnimationAtTimeOnElementWithId("anim5", 0.1, "box5"))
result += "FAIL - box5 animation was running<br>";
else
......
PASS - "left" property for "box1" element at 1s saw something close to: 200
PASS - "webkitTransform.4" property for "box2" element at 1s saw something close to: 200
PASS - "opacity" property for "box1" element at 0.5s saw something close to: 0.5
PASS - "opacity" property for "box1" element at 1s saw something close to: 0
PASS - "left" property for "box1" element at 1.5s saw something close to: 300
PASS - "webkitTransform.4" property for "box2" element at 1.5s saw something close to: 300
PASS - "opacity" property for "box1" element at 1.5s saw something close to: 0.5
PASS - "left" property for "box1" element at 1s saw something close to: 100
PASS - "left" property for "box1" element at 2s saw something close to: 0
PASS - "left" property for "box1" element at 3s saw something close to: 100
<!DOCTYPE html>
<html>
<head>
<style type="text/css" media="screen">
#box1 {
position: relative;
height: 100px;
width: 100px;
left: 0;
background-color: blue;
margin: 0;
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: 2;
-webkit-animation-direction: alternate;
-webkit-animation-name: move;
}
@-webkit-keyframes move {
from {
opacity: 1;
}
50% {
opacity: 1;
left: 100px;
}
to {
opacity: 1;
}
}
/* Test reversing animation with missing values */
</style>
<script src="animation-test-helpers.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
const expectedValues = [
// [animation-name, time, element-id, property, expected-value, tolerance]
["move", 1, "box1", "left", 100, 15],
["move", 2, "box1", "left", 0, 15],
["move", 3, "box1", "left", 100, 15],
];
runAnimationTest(expectedValues);
</script>
</head>
<body>
<div id="box1"></div>
<div id="result">
</div>
</body>
</html>
PASS - "left" property for "box1" element at 0.5s saw something close to: 132
PASS - "webkitTransform.4" property for "box2" element at 0.5s saw something close to: 132
PASS - "left" property for "box1" element at 1.5s saw something close to: 300
PASS - "webkitTransform.4" property for "box2" element at 1.5s saw something close to: 300
<!DOCTYPE html>
<html>
<head>
<style type="text/css" media="screen">
.box {
position: relative;
margin: 10px;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: ease-in;
}
#box1 {
-webkit-animation-name: move;
}
@-webkit-keyframes move {
from {
opacity: 0;
left: 100px;
}
25% {
opacity: 0.25;
}
50% {
left: 200px;
-webkit-animation-timing-function: linear;
}
to {
left: 400px;
}
}
#box2 {
-webkit-animation-name: move2;
}
@-webkit-keyframes move2 {
from {
opacity: 0;
-webkit-transform: translateX(100px);
}
25% {
opacity: 0.25;
}
50% {
-webkit-transform: translateX(200px);
-webkit-animation-timing-function: linear;
}
to {
-webkit-transform: translateX(400px);
}
}
</style>
<script src="animation-test-helpers.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
const expectedValues = [
// [animation-name, time, element-id, property, expected-value, tolerance]
["move", 0.5, "box1", "left", 132, 15],
["move2", 0.5, "box2", "webkitTransform.4", 132, 15],
["move", 1.5, "box1", "left", 300, 15],
["move2", 1.5, "box2", "webkitTransform.4", 300, 15],
];
runAnimationTest(expectedValues);
</script>
</head>
<body>
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="result">
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css" media="screen">
.box {
position: relative;
margin: 10px;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: linear;
}
#box1 {
-webkit-animation-name: move;
}
@-webkit-keyframes move {
from {
left: 0px;
}
50% {
opacity: 0;
}
to {
left: 400px;
}
}
#box2 {
-webkit-animation-name: move2;
}
@-webkit-keyframes move2 {
from {
-webkit-transform: translateX(0);
}
50% {
opacity: 0;
}
to {
-webkit-transform: translateX(400px);
}
}
</style>
<script src="animation-test-helpers.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
const expectedValues = [
// [animation-name, time, element-id, property, expected-value, tolerance]
["move", 1, "box1", "left", 200, 15],
["move2", 1, "box2", "webkitTransform.4", 200, 15],
["move", 0.5, "box1", "opacity", 0.5, 0.1],
["move", 1, "box1", "opacity", 0, 0.1],
["move", 1.5, "box1", "left", 300, 15],
["move2", 1.5, "box2", "webkitTransform.4", 300, 15],
["move", 1.5, "box1", "opacity", 0.5, 0.1],
];
runAnimationTest(expectedValues);
</script>
</head>
<body>
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="result">
</div>
</body>
</html>
2010-08-29 Simon Fraser <simon.fraser@apple.com>
Reviewed by Darin Adler.
When properties are missing from animation keyframes, interpolate between those keyframes that specify them
https://bugs.webkit.org/show_bug.cgi?id=40794
When a property does not appear in all keyframes of a keyframe animation, we currently use the
value of that property from the unanimated style. That forces the author to use additional
keyframes for properties that need to "skip a keyframe", which is laborious.
With this change, properties are interpolated between the keyframes in which they appear.
This is equivalent to splitting each property out into its own set of keyframes.
Tests: animations/missing-keyframe-properties-repeating.html
animations/missing-keyframe-properties-timing-function.html
animations/missing-keyframe-properties.html
* css/CSSStyleSelector.h:
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::styleForKeyframe): Pass a KeyframeValue in so that we can
collect which properties are represented per keyframe.
(WebCore::CSSStyleSelector::keyframeStylesForAnimation): Keyframes are inserted into a
KeyframeList by object now, rather than by key and style.
* page/animation/AnimationBase.cpp:
(WebCore::AnimationBase::progress): Use AnimationDirectionAlternate for readability.
* page/animation/KeyframeAnimation.cpp:
(WebCore::KeyframeAnimation::fetchIntervalEndpointsForProperty): Renamed from getKeyframeAnimationInterval.
Use fractionalTime etc to match AnimationBase::progress(), and do lookups per-property.
Simplify the code that finds the relevant keyframe to do less work.
(WebCore::KeyframeAnimation::animate): Call fetchIntervalEndpointsForProperty() for each property, rather than just once for the
entire keyframe.
(WebCore::KeyframeAnimation::getAnimatedStyle): Ditto.
(WebCore::KeyframeAnimation::hasAnimationForProperty): FIXME comment.
* page/animation/KeyframeAnimation.h: Rename getKeyframeAnimationInterval() to fetchIntervalEndpointsForProperty().
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::startAnimation): For hardware animations, only insert values
for keyframes which contain the property.
(WebCore::KeyframeList::KeyframeList): insert() takes a KeyframeValue now.
* rendering/style/KeyframeList.cpp:
(WebCore::KeyframeList::operator==):
(WebCore::KeyframeList::insert): Fix insert/replace logic, and ensure we maintain the
m_properties hash.
* rendering/style/KeyframeList.h:
(WebCore::KeyframeValue::KeyframeValue): Make members private, with accessors.
Add a m_properties HashSet for the properties animated in this keyframe.
2010-08-29 Csaba Osztrogonác <ossy@webkit.org>
Reviewed by Darin Adler.
......@@ -1373,7 +1373,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
return m_style.release();
}
PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeList& list)
PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
{
if (keyframeRule->style())
addMatchedDeclaration(keyframeRule->style());
......@@ -1410,7 +1410,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* el
// Start loading images referenced by this style.
loadPendingImages();
// Add all the animating properties to the list
// Add all the animating properties to the keyframe.
if (keyframeRule->style()) {
CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
......@@ -1418,7 +1418,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* el
// Timing-function within keyframes is special, because it is not animated; it just
// describes the timing function between this keyframe and the next.
if (property != CSSPropertyWebkitAnimationTimingFunction)
list.addProperty(property);
keyframe.addProperty(property);
}
}
......@@ -1439,7 +1439,6 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle*
return;
const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
RefPtr<RenderStyle> keyframeStyle;
// Construct and populate the style for each keyframe
for (unsigned i = 0; i < rule->length(); ++i) {
......@@ -1448,34 +1447,36 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle*
initForStyleResolve(e);
const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
keyframeStyle = styleForKeyframe(elementStyle, keyframeRule, list);
KeyframeValue keyframe(0, 0);
keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
// Add this keyframe style to all the indicated key times
Vector<float> keys;
keyframeRule->getKeys(keys);
for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
float key = keys[keyIndex];
list.insert(key, keyframeStyle.get());
keyframe.setKey(keys[keyIndex]);
list.insert(keyframe);
}
keyframeStyle.release();
}
// If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
int initialListSize = list.size();
if (initialListSize > 0 && list[0].key() != 0) {
RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create();
keyframe->setKeyText("0%");
keyframeStyle = styleForKeyframe(elementStyle, keyframe.get(), list);
list.insert(0, keyframeStyle.release());
RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
keyframeRule->setKeyText("0%");
KeyframeValue keyframe(0, 0);
keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
list.insert(keyframe);
}
// If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create();
keyframe->setKeyText("100%");
keyframeStyle = styleForKeyframe(elementStyle, keyframe.get(), list);
list.insert(1, keyframeStyle.release());
RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
keyframeRule->setKeyText("100%");
KeyframeValue keyframe(1, 0);
keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
list.insert(keyframe);
}
}
......
......@@ -59,6 +59,7 @@ class Frame;
class FrameView;
class KURL;
class KeyframeList;
class KeyframeValue;
class MediaQueryEvaluator;
class Node;
class Settings;
......@@ -114,7 +115,7 @@ public:
RenderStyle* style() const { return m_style.get(); }
PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeList&);
PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&);
public:
// These methods will give back the set of rules that matched for a given element (or a pseudo-element).
......
......@@ -1242,7 +1242,7 @@ double AnimationBase::progress(double scale, double offset, const TimingFunction
int integralTime = static_cast<int>(fractionalTime);
fractionalTime -= integralTime;
if (m_animation->direction() && (integralTime & 1))
if ((m_animation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1))
fractionalTime = 1 - fractionalTime;
if (scale != 1 || offset)
......
......@@ -62,42 +62,67 @@ KeyframeAnimation::~KeyframeAnimation()
endAnimation();
}
void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const
void KeyframeAnimation::fetchIntervalEndpointsForProperty(int property, const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const
{
// Find the first key
double elapsedTime = getElapsedTime();
double t = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1;
double fractionalTime = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1;
ASSERT(t >= 0);
if (t < 0)
t = 0;
ASSERT(fractionalTime >= 0);
if (fractionalTime < 0)
fractionalTime = 0;
int i = static_cast<int>(t);
t -= i;
if (m_animation->direction() && (i & 1))
t = 1 - t;
// FIXME: share this code with AnimationBase::progress().
int iteration = static_cast<int>(fractionalTime);
fractionalTime -= iteration;
bool reversing = (m_animation->direction() == Animation::AnimationDirectionAlternate) && (iteration & 1);
if (reversing)
fractionalTime = 1 - fractionalTime;
double scale = 1;
double offset = 0;
size_t numKeyframes = m_keyframes.size();
if (!numKeyframes)
return;
ASSERT(!m_keyframes[0].key());
ASSERT(m_keyframes[m_keyframes.size() - 1].key() == 1);
int prevIndex = -1;
int nextIndex = -1;
// FIXME: with a lot of keys, this linear search will be slow. We could binary search.
for (size_t i = 0; i < numKeyframes; ++i) {
const KeyframeValue& currentKeyframe = m_keyframes[i];
if (t < currentKeyframe.key()) {
// The first key should always be 0, so we should never succeed on the first key
if (!fromStyle)
break;
scale = 1.0 / (currentKeyframe.key() - offset);
toStyle = currentKeyframe.style();
const KeyframeValue& currKeyFrame = m_keyframes[i];
if (!currKeyFrame.containsProperty(property))
continue;
if (fractionalTime < currKeyFrame.key()) {
nextIndex = i;
break;
}
offset = currentKeyframe.key();
fromStyle = currentKeyframe.style();
prevIndex = i;
}
if (!fromStyle || !toStyle)
return;
double scale = 1;
double offset = 0;
if (prevIndex == -1)
prevIndex = 0;
if (nextIndex == -1)
nextIndex = m_keyframes.size() - 1;
const KeyframeValue& prevKeyframe = m_keyframes[prevIndex];
const KeyframeValue& nextKeyframe = m_keyframes[nextIndex];
fromStyle = prevKeyframe.style();
toStyle = nextKeyframe.style();
offset = prevKeyframe.key();
scale = 1.0 / (nextKeyframe.key() - prevKeyframe.key());
const TimingFunction* timingFunction = 0;
if (fromStyle->animations() && fromStyle->animations()->size() > 0) {
......@@ -132,18 +157,9 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
// through to the style blend so that we get the fromStyle.
if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards())
return;
// FIXME: we need to be more efficient about determining which keyframes we are animating between.
// We should cache the last pair or something.
// Get the from/to styles and progress between
const RenderStyle* fromStyle = 0;
const RenderStyle* toStyle = 0;
double progress;
getKeyframeAnimationInterval(fromStyle, toStyle, progress);
// If either style is 0 we have an invalid case, just stop the animation.
if (!fromStyle || !toStyle) {
// If we have no keyframes, don't animate.
if (!m_keyframes.size()) {
updateStateMachine(AnimationStateInputEndAnimation, -1);
return;
}
......@@ -153,9 +169,19 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
if (!animatedStyle)
animatedStyle = RenderStyle::clone(targetStyle);
// FIXME: we need to be more efficient about determining which keyframes we are animating between.
// We should cache the last pair or something.
HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) {
bool needsAnim = blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress);
int property = *it;
// Get the from/to styles and progress between
const RenderStyle* fromStyle = 0;
const RenderStyle* toStyle = 0;
double progress;
fetchIntervalEndpointsForProperty(property, fromStyle, toStyle, progress);
bool needsAnim = blendProperties(this, property, animatedStyle.get(), fromStyle, toStyle, progress);
if (needsAnim)
setAnimating();
else {
......@@ -176,26 +202,29 @@ void KeyframeAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle)
if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards())
return;
// Get the from/to styles and progress between
const RenderStyle* fromStyle = 0;
const RenderStyle* toStyle = 0;
double progress;
getKeyframeAnimationInterval(fromStyle, toStyle, progress);
// If either style is 0 we have an invalid case
if (!fromStyle || !toStyle)
if (!m_keyframes.size())
return;
if (!animatedStyle)
animatedStyle = RenderStyle::clone(m_object->style());
HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it)
blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress);
for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) {
int property = *it;
// Get the from/to styles and progress between
const RenderStyle* fromStyle = 0;
const RenderStyle* toStyle = 0;
double progress;
fetchIntervalEndpointsForProperty(property, fromStyle, toStyle, progress);
blendProperties(this, property, animatedStyle.get(), fromStyle, toStyle, progress);
}
}
bool KeyframeAnimation::hasAnimationForProperty(int property) const
{
// FIXME: why not just m_keyframes.containsProperty()?
HashSet<int>::const_iterator end = m_keyframes.endProperties();
for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != end; ++it) {
if (*it == property)
......
......@@ -82,8 +82,8 @@ private:
KeyframeAnimation(const Animation* animation, RenderObject*, int index, CompositeAnimation*, RenderStyle* unanimatedStyle);
virtual ~KeyframeAnimation();
// Get the styles surrounding the current animation time and the progress between them
void getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& progress) const;
// Get the styles for the given property surrounding the current animation time and the progress between them.
void fetchIntervalEndpointsForProperty(int property, const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& progress) const;
// The keyframes that we are blending.
KeyframeList m_keyframes;
......
......@@ -1126,10 +1126,10 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim
// get timing function
const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0;
if (hasTransform)
if (currentKeyframe.containsProperty(AnimatedPropertyWebkitTransform))
transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
if (hasOpacity)
if (currentKeyframe.containsProperty(AnimatedPropertyOpacity))
opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
}
......
......@@ -43,10 +43,10 @@ bool KeyframeList::operator==(const KeyframeList& o) const
Vector<KeyframeValue>::const_iterator it2 = o.m_keyframes.begin();
for (Vector<KeyframeValue>::const_iterator it1 = m_keyframes.begin(); it1 != m_keyframes.end(); ++it1) {
if (it1->m_key != it2->m_key)
if (it1->key() != it2->key())
return false;
const RenderStyle& style1 = *it1->m_style;
const RenderStyle& style2 = *it2->m_style;
const RenderStyle& style1 = *it1->style();
const RenderStyle& style2 = *it2->style();
if (style1 != style2)
return false;
++it2;
......@@ -55,34 +55,43 @@ bool KeyframeList::operator==(const KeyframeList& o) const
return true;
}
void KeyframeList::insert(float key, PassRefPtr<RenderStyle> style)
void KeyframeList::insert(const KeyframeValue& keyframe)