Index: Source/core/css/resolver/StyleResolver.cpp |
diff --git a/Source/core/css/resolver/StyleResolver.cpp b/Source/core/css/resolver/StyleResolver.cpp |
index 5c48aa1d0c3e5926abac9e466b23de34fa55ac9f..d37e8a32e9f582b945ccd2be4e486c7ba10034f2 100644 |
--- a/Source/core/css/resolver/StyleResolver.cpp |
+++ b/Source/core/css/resolver/StyleResolver.cpp |
@@ -772,10 +772,9 @@ void StyleResolver::resolveKeyframes(Element* element, const RenderStyle* style, |
// Construct and populate the style for each keyframe |
const Vector<RefPtr<StyleKeyframe> >& styleKeyframes = keyframesRule->keyframes(); |
- for (unsigned i = 0; i < styleKeyframes.size(); ++i) { |
+ for (size_t i = 0; i < styleKeyframes.size(); ++i) { |
const StyleKeyframe* styleKeyframe = styleKeyframes[i].get(); |
RefPtr<RenderStyle> keyframeStyle = styleForKeyframe(element, style, styleKeyframe); |
- |
Vector<float> offsets; |
styleKeyframe->getKeys(offsets); |
for (size_t j = 0; j < offsets.size(); ++j) { |
@@ -785,15 +784,56 @@ void StyleResolver::resolveKeyframes(Element* element, const RenderStyle* style, |
// FIXME: AnimatableValues should be shared between the keyframes at different offsets. |
for (unsigned k = 0; k < properties->propertyCount(); k++) { |
CSSPropertyID property = properties->propertyAt(k).id(); |
- // FIXME: CSSValue needs to be resolved. |
keyframe->setPropertyValue(property, CSSAnimatableValueFactory::create(property, keyframeStyle.get()).get()); |
} |
keyframes.append(keyframe); |
} |
} |
- // FIXME: If the 0% keyframe is missing, create it (but only if there is at least one other keyframe) |
- // FIXME: If the 100% keyframe is missing, create it (but only if there is at least one other keyframe) |
+ if (keyframes.isEmpty()) |
+ return; |
+ |
+ // Remove duplicate keyframes. In CSS the last keyframe at a given offset takes priority. |
+ size_t targetIndex = 0; |
+ for (size_t i = 1; i < keyframes.size(); i++) { |
+ if (keyframes[i]->offset() != keyframes[targetIndex]->offset()) |
+ targetIndex++; |
+ if (targetIndex != i) |
+ keyframes[targetIndex] = keyframes[i]; |
+ } |
+ keyframes.shrink(targetIndex + 1); |
+ |
+ bool isStartKeyframeMissing = keyframes[0]->offset(); |
+ bool isEndKeyframeMissing = keyframes[keyframes.size() - 1]->offset() != 1; |
+ if (!isStartKeyframeMissing && !isEndKeyframeMissing) |
+ return; |
+ |
+ HashSet<CSSPropertyID> allProperties; |
+ for (size_t i = 0; i < styleKeyframes.size(); ++i) { |
+ const StyleKeyframe* styleKeyframe = styleKeyframes[i].get(); |
+ Vector<float> offsets; |
+ styleKeyframe->getKeys(offsets); |
+ const StylePropertySet* properties = styleKeyframe->properties(); |
+ for (unsigned j = 0; j < properties->propertyCount(); ++j) { |
+ allProperties.add(properties->propertyAt(j).id()); |
+ } |
+ } |
+ |
+ if (isStartKeyframeMissing) { |
+ RefPtr<Keyframe> keyframe = Keyframe::create(); |
+ keyframe->setOffset(0); |
+ for (HashSet<CSSPropertyID>::const_iterator iter = allProperties.begin(); iter != allProperties.end(); ++iter) |
+ keyframe->setPropertyValue(*iter, CSSAnimatableValueFactory::create(*iter, style).get()); |
+ keyframes.prepend(keyframe); |
+ } |
+ |
+ if (isEndKeyframeMissing) { |
+ RefPtr<Keyframe> keyframe = Keyframe::create(); |
+ keyframe->setOffset(1); |
+ for (HashSet<CSSPropertyID>::const_iterator iter = allProperties.begin(); iter != allProperties.end(); ++iter) |
+ keyframe->setPropertyValue(*iter, CSSAnimatableValueFactory::create(*iter, style).get()); |
+ keyframes.append(keyframe); |
+ } |
} |
const StylePropertySet* StyleResolver::firstKeyframeStyles(const Element* element, const StringImpl* animationName) |