#ifndef KeyframeEffectModel_h
#define KeyframeEffectModel_h
-#include "core/animation/AnimatableValue.h"
+#include "core/animation/AnimatableValueKeyframe.h"
#include "core/animation/AnimationEffect.h"
+#include "core/animation/InterpolationEffect.h"
+#include "core/animation/StringKeyframe.h"
+#include "core/animation/TimedItem.h"
#include "platform/animation/TimingFunction.h"
+#include "platform/heap/Handle.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/PassOwnPtr.h"
namespace WebCore {
-typedef HashSet<CSSPropertyID> PropertySet;
-
+class Element;
class KeyframeEffectModelTest;
-// Represents the keyframes set through the API.
-class Keyframe : public RefCounted<Keyframe> {
-public:
- static PassRefPtr<Keyframe> create()
- {
- return adoptRef(new Keyframe);
- }
- static bool compareOffsets(const RefPtr<Keyframe>& a, const RefPtr<Keyframe>& b)
- {
- return a->offset() < b->offset();
- }
- void setOffset(double offset) { m_offset = offset; }
- double offset() const { return m_offset; }
- void setComposite(AnimationEffect::CompositeOperation composite) { m_composite = composite; }
- AnimationEffect::CompositeOperation composite() const { return m_composite; }
- void setEasing(PassRefPtr<TimingFunction> easing) { m_easing = easing; }
- TimingFunction* easing() const { return m_easing.get(); }
- void setPropertyValue(CSSPropertyID, const AnimatableValue*);
- void clearPropertyValue(CSSPropertyID);
- const AnimatableValue* propertyValue(CSSPropertyID) const;
- PropertySet properties() const;
- PassRefPtr<Keyframe> clone() const { return adoptRef(new Keyframe(*this)); }
- PassRefPtr<Keyframe> cloneWithOffset(double offset) const;
-private:
- Keyframe();
- Keyframe(const Keyframe&);
- double m_offset;
- AnimationEffect::CompositeOperation m_composite;
- RefPtr<TimingFunction> m_easing;
- typedef HashMap<CSSPropertyID, RefPtr<AnimatableValue> > PropertyValueMap;
- PropertyValueMap m_propertyValues;
-};
-
-class KeyframeEffectModel FINAL : public AnimationEffect {
+class KeyframeEffectModelBase : public AnimationEffect {
public:
- class PropertySpecificKeyframe;
- typedef Vector<RefPtr<Keyframe> > KeyframeVector;
- typedef Vector<OwnPtr<PropertySpecificKeyframe> > PropertySpecificKeyframeVector;
// FIXME: Implement accumulation.
- static PassRefPtr<KeyframeEffectModel> create(const KeyframeVector& keyframes)
- {
- return adoptRef(new KeyframeEffectModel(keyframes));
- }
- virtual bool affects(CSSPropertyID property) OVERRIDE
- {
- ensureKeyframeGroups();
- return m_keyframeGroups->contains(property);
- }
-
- // AnimationEffect implementation.
- virtual PassOwnPtr<CompositableValueList> sample(int iteration, double fraction) const OVERRIDE;
-
- // FIXME: Implement setFrames()
- const KeyframeVector& getFrames() const { return m_keyframes; }
-
- virtual bool isKeyframeEffectModel() const OVERRIDE { return true; }
+ typedef WillBeHeapVector<OwnPtrWillBeMember<Keyframe::PropertySpecificKeyframe> > PropertySpecificKeyframeVector;
+ class PropertySpecificKeyframeGroup : public NoBaseWillBeGarbageCollected<PropertySpecificKeyframeGroup> {
+ public:
+ void appendKeyframe(PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe>);
+ const PropertySpecificKeyframeVector& keyframes() const { return m_keyframes; }
- PropertySet properties() const;
+ void trace(Visitor*);
- class PropertySpecificKeyframe {
- public:
- PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, const AnimatableValue*, CompositeOperation);
- double offset() const { return m_offset; }
- const TimingFunction* easing() const { return m_easing.get(); }
- const CompositableValue* value() const { return m_value.get(); }
- PassOwnPtr<PropertySpecificKeyframe> cloneWithOffset(double offset) const;
private:
- // Used by cloneWithOffset().
- PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, PassRefPtr<CompositableValue>);
- double m_offset;
- RefPtr<TimingFunction> m_easing;
- RefPtr<CompositableValue> m_value;
- };
+ void removeRedundantKeyframes();
+ void addSyntheticKeyframeIfRequired(const KeyframeEffectModelBase* context);
- class PropertySpecificKeyframeGroup {
- public:
- void appendKeyframe(PassOwnPtr<PropertySpecificKeyframe>);
- PassRefPtr<CompositableValue> sample(int iteration, double offset) const;
- const PropertySpecificKeyframeVector& keyframes() const { return m_keyframes; }
- private:
PropertySpecificKeyframeVector m_keyframes;
- void removeRedundantKeyframes();
- void addSyntheticKeyframeIfRequired();
- friend class KeyframeEffectModel;
+ friend class KeyframeEffectModelBase;
};
+ bool isReplaceOnly();
+
+ PropertySet properties() const;
+
+ typedef WillBeHeapVector<RefPtrWillBeMember<Keyframe> > KeyframeVector;
+ const KeyframeVector& getFrames() const { return m_keyframes; }
+ // FIXME: Implement setFrames()
+
const PropertySpecificKeyframeVector& getPropertySpecificKeyframes(CSSPropertyID id) const
{
ensureKeyframeGroups();
return m_keyframeGroups->get(id)->keyframes();
}
-private:
- KeyframeEffectModel(const KeyframeVector& keyframes);
+ // AnimationEffect implementation.
+ virtual PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > sample(int iteration, double fraction, double iterationDuration) const OVERRIDE;
+
+ virtual bool isKeyframeEffectModel() const OVERRIDE { return true; }
+
+ virtual bool isAnimatableValueKeyframeEffectModel() const { return false; }
+ virtual bool isStringKeyframeEffectModel() const { return false; }
+ virtual void trace(Visitor*) OVERRIDE;
+
+ // FIXME: This is a hack used to resolve CSSValues to AnimatableValues while we have a valid handle on an element.
+ // This should be removed once StringKeyframes no longer uses InterpolableAnimatableValues.
+ void forceConversionsToAnimatableValues(Element* element)
+ {
+ ensureKeyframeGroups();
+ ensureInterpolationEffect(element);
+ }
+
+protected:
static KeyframeVector normalizedKeyframes(const KeyframeVector& keyframes);
// Lazily computes the groups of property-specific keyframes.
void ensureKeyframeGroups() const;
+ void ensureInterpolationEffect(Element* = 0) const;
KeyframeVector m_keyframes;
// The spec describes filtering the normalized keyframes at sampling time
// to get the 'property-specific keyframes'. For efficiency, we cache the
// property-specific lists.
- typedef HashMap<CSSPropertyID, OwnPtr<PropertySpecificKeyframeGroup> > KeyframeGroupMap;
- mutable OwnPtr<KeyframeGroupMap> m_keyframeGroups;
+ typedef WillBeHeapHashMap<CSSPropertyID, OwnPtrWillBeMember<PropertySpecificKeyframeGroup> > KeyframeGroupMap;
+ mutable OwnPtrWillBeMember<KeyframeGroupMap> m_keyframeGroups;
+ mutable RefPtrWillBeMember<InterpolationEffect> m_interpolationEffect;
friend class KeyframeEffectModelTest;
+
+ bool affects(CSSPropertyID property)
+ {
+ ensureKeyframeGroups();
+ return m_keyframeGroups->contains(property);
+ }
};
-DEFINE_TYPE_CASTS(KeyframeEffectModel, AnimationEffect, value, value->isKeyframeEffectModel(), value.isKeyframeEffectModel());
+template <class Keyframe>
+class KeyframeEffectModel FINAL : public KeyframeEffectModelBase {
+public:
+ typedef WillBeHeapVector<RefPtrWillBeMember<Keyframe> > KeyframeVector;
+ static PassRefPtrWillBeRawPtr<KeyframeEffectModel<Keyframe> > create(const KeyframeVector& keyframes) { return adoptRefWillBeNoop(new KeyframeEffectModel(keyframes)); }
+
+private:
+ KeyframeEffectModel(const KeyframeVector& keyframes)
+ {
+ m_keyframes.appendVector(keyframes);
+ }
+
+ virtual bool isAnimatableValueKeyframeEffectModel() const { return false; }
+ virtual bool isStringKeyframeEffectModel() const { return false; }
+
+};
+
+typedef KeyframeEffectModelBase::KeyframeVector KeyframeVector;
+typedef KeyframeEffectModelBase::PropertySpecificKeyframeVector PropertySpecificKeyframeVector;
+
+typedef KeyframeEffectModel<AnimatableValueKeyframe> AnimatableValueKeyframeEffectModel;
+typedef AnimatableValueKeyframeEffectModel::KeyframeVector AnimatableValueKeyframeVector;
+typedef AnimatableValueKeyframeEffectModel::PropertySpecificKeyframeVector AnimatableValuePropertySpecificKeyframeVector;
+
+typedef KeyframeEffectModel<StringKeyframe> StringKeyframeEffectModel;
+typedef StringKeyframeEffectModel::KeyframeVector StringKeyframeVector;
+typedef StringKeyframeEffectModel::PropertySpecificKeyframeVector StringPropertySpecificKeyframeVector;
+
+DEFINE_TYPE_CASTS(KeyframeEffectModelBase, AnimationEffect, value, value->isKeyframeEffectModel(), value.isKeyframeEffectModel());
+DEFINE_TYPE_CASTS(AnimatableValueKeyframeEffectModel, KeyframeEffectModelBase, value, value->isAnimatableValueKeyframeEffectModel(), value.isAnimatableValueKeyframeEffectModel());
+
+inline const AnimatableValueKeyframeEffectModel* toAnimatableValueKeyframeEffectModel(const AnimationEffect* base)
+{
+ return toAnimatableValueKeyframeEffectModel(toKeyframeEffectModelBase(base));
+}
+
+inline AnimatableValueKeyframeEffectModel* toAnimatableValueKeyframeEffectModel(AnimationEffect* base)
+{
+ return toAnimatableValueKeyframeEffectModel(toKeyframeEffectModelBase(base));
+}
+
+template <>
+inline bool KeyframeEffectModel<AnimatableValueKeyframe>::isAnimatableValueKeyframeEffectModel() const { return true; }
+
+template <>
+inline bool KeyframeEffectModel<StringKeyframe>::isStringKeyframeEffectModel() const { return true; }
} // namespace WebCore