OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 18 matching lines...) Expand all Loading... |
29 */ | 29 */ |
30 | 30 |
31 #include "config.h" | 31 #include "config.h" |
32 #include "core/animation/KeyframeEffectModel.h" | 32 #include "core/animation/KeyframeEffectModel.h" |
33 | 33 |
34 #include "core/animation/TimedItem.h" | 34 #include "core/animation/TimedItem.h" |
35 #include "wtf/text/StringHash.h" | 35 #include "wtf/text/StringHash.h" |
36 | 36 |
37 namespace WebCore { | 37 namespace WebCore { |
38 | 38 |
39 bool Keyframe::compareOffsets(const RefPtrWillBeRawPtr<Keyframe>& a, const RefPt
rWillBeRawPtr<Keyframe>& b) | 39 Keyframe::Keyframe() |
| 40 : m_offset(nullValue()) |
| 41 , m_composite(AnimationEffect::CompositeReplace) |
| 42 , m_easing(LinearTimingFunction::preset()) |
| 43 { } |
| 44 |
| 45 Keyframe::Keyframe(const Keyframe& copyFrom) |
| 46 : m_offset(copyFrom.m_offset) |
| 47 , m_composite(copyFrom.m_composite) |
| 48 , m_easing(copyFrom.m_easing) |
40 { | 49 { |
41 return a->offset() < b->offset(); | 50 ASSERT(m_easing); |
| 51 for (PropertyValueMap::const_iterator iter = copyFrom.m_propertyValues.begin
(); iter != copyFrom.m_propertyValues.end(); ++iter) |
| 52 setPropertyValue(iter->key, iter->value.get()); |
42 } | 53 } |
43 | 54 |
44 PropertySet KeyframeEffectModelBase::properties() const | 55 void Keyframe::setEasing(PassRefPtr<TimingFunction> easing) |
| 56 { |
| 57 ASSERT(easing); |
| 58 m_easing = easing; |
| 59 } |
| 60 |
| 61 void Keyframe::setPropertyValue(CSSPropertyID property, const AnimatableValue* v
alue) |
| 62 { |
| 63 m_propertyValues.add(property, const_cast<AnimatableValue*>(value)); |
| 64 } |
| 65 |
| 66 void Keyframe::clearPropertyValue(CSSPropertyID property) |
| 67 { |
| 68 m_propertyValues.remove(property); |
| 69 } |
| 70 |
| 71 const AnimatableValue* Keyframe::propertyValue(CSSPropertyID property) const |
| 72 { |
| 73 ASSERT(m_propertyValues.contains(property)); |
| 74 return m_propertyValues.get(property); |
| 75 } |
| 76 |
| 77 PropertySet Keyframe::properties() const |
| 78 { |
| 79 // This is not used in time-critical code, so we probably don't need to |
| 80 // worry about caching this result. |
| 81 PropertySet properties; |
| 82 for (PropertyValueMap::const_iterator iter = m_propertyValues.begin(); iter
!= m_propertyValues.end(); ++iter) |
| 83 properties.add(*iter.keys()); |
| 84 return properties; |
| 85 } |
| 86 |
| 87 PassRefPtrWillBeRawPtr<Keyframe> Keyframe::cloneWithOffset(double offset) const |
| 88 { |
| 89 RefPtrWillBeRawPtr<Keyframe> theClone = clone(); |
| 90 theClone->setOffset(offset); |
| 91 return theClone.release(); |
| 92 } |
| 93 |
| 94 void Keyframe::trace(Visitor* visitor) |
| 95 { |
| 96 visitor->trace(m_propertyValues); |
| 97 } |
| 98 |
| 99 KeyframeEffectModel::KeyframeEffectModel(const KeyframeVector& keyframes) |
| 100 : m_keyframes(keyframes) |
| 101 { |
| 102 } |
| 103 |
| 104 PropertySet KeyframeEffectModel::properties() const |
45 { | 105 { |
46 PropertySet result; | 106 PropertySet result; |
47 if (!m_keyframes.size()) { | 107 if (!m_keyframes.size()) { |
48 return result; | 108 return result; |
49 } | 109 } |
50 result = m_keyframes[0]->properties(); | 110 result = m_keyframes[0]->properties(); |
51 for (size_t i = 1; i < m_keyframes.size(); i++) { | 111 for (size_t i = 1; i < m_keyframes.size(); i++) { |
52 PropertySet extras = m_keyframes[i]->properties(); | 112 PropertySet extras = m_keyframes[i]->properties(); |
53 for (PropertySet::const_iterator it = extras.begin(); it != extras.end()
; ++it) { | 113 for (PropertySet::const_iterator it = extras.begin(); it != extras.end()
; ++it) { |
54 result.add(*it); | 114 result.add(*it); |
55 } | 115 } |
56 } | 116 } |
57 return result; | 117 return result; |
58 } | 118 } |
59 | 119 |
60 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > Ke
yframeEffectModelBase::sample(int iteration, double fraction, double iterationDu
ration) const | 120 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > Ke
yframeEffectModel::sample(int iteration, double fraction, double iterationDurati
on) const |
61 { | 121 { |
62 ASSERT(iteration >= 0); | 122 ASSERT(iteration >= 0); |
63 ASSERT(!isNull(fraction)); | 123 ASSERT(!isNull(fraction)); |
64 ensureKeyframeGroups(); | 124 ensureKeyframeGroups(); |
65 ensureInterpolationEffect(); | 125 ensureInterpolationEffect(); |
66 | 126 |
67 return m_interpolationEffect->getActiveInterpolations(fraction, iterationDur
ation); | 127 return m_interpolationEffect->getActiveInterpolations(fraction, iterationDur
ation); |
68 } | 128 } |
69 | 129 |
70 KeyframeEffectModelBase::KeyframeVector KeyframeEffectModelBase::normalizedKeyfr
ames(const KeyframeVector& keyframes) | 130 KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(con
st KeyframeVector& keyframes) |
71 { | 131 { |
72 // keyframes [beginIndex, endIndex) will remain after removing all keyframes
if they are not | 132 // keyframes [beginIndex, endIndex) will remain after removing all keyframes
if they are not |
73 // loosely sorted by offset, and after removing keyframes with positional of
fset outide [0, 1]. | 133 // loosely sorted by offset, and after removing keyframes with positional of
fset outide [0, 1]. |
74 size_t beginIndex = 0; | 134 size_t beginIndex = 0; |
75 size_t endIndex = keyframes.size(); | 135 size_t endIndex = keyframes.size(); |
76 | 136 |
77 // Becomes the most recent keyframe with an explicit offset. | 137 // Becomes the most recent keyframe with an explicit offset. |
78 size_t lastIndex = endIndex; | 138 size_t lastIndex = endIndex; |
79 double lastOffset = std::numeric_limits<double>::quiet_NaN(); | 139 double lastOffset = std::numeric_limits<double>::quiet_NaN(); |
80 | 140 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 result[lastIndex + j]->setOffset(lastOffset + (offset -
lastOffset) * j / (i - lastIndex)); | 184 result[lastIndex + j]->setOffset(lastOffset + (offset -
lastOffset) * j / (i - lastIndex)); |
125 } | 185 } |
126 lastIndex = i; | 186 lastIndex = i; |
127 lastOffset = offset; | 187 lastOffset = offset; |
128 } | 188 } |
129 } | 189 } |
130 } | 190 } |
131 return result; | 191 return result; |
132 } | 192 } |
133 | 193 |
134 | 194 void KeyframeEffectModel::ensureKeyframeGroups() const |
135 void KeyframeEffectModelBase::ensureKeyframeGroups() const | |
136 { | 195 { |
137 if (m_keyframeGroups) | 196 if (m_keyframeGroups) |
138 return; | 197 return; |
139 | 198 |
140 m_keyframeGroups = adoptPtrWillBeNoop(new KeyframeGroupMap); | 199 m_keyframeGroups = adoptPtrWillBeNoop(new KeyframeGroupMap); |
141 const KeyframeVector keyframes = normalizedKeyframes(getFrames()); | 200 const KeyframeVector keyframes = normalizedKeyframes(getFrames()); |
142 for (KeyframeVector::const_iterator keyframeIter = keyframes.begin(); keyfra
meIter != keyframes.end(); ++keyframeIter) { | 201 for (KeyframeVector::const_iterator keyframeIter = keyframes.begin(); keyfra
meIter != keyframes.end(); ++keyframeIter) { |
143 const Keyframe* keyframe = keyframeIter->get(); | 202 const Keyframe* keyframe = keyframeIter->get(); |
144 PropertySet keyframeProperties = keyframe->properties(); | 203 PropertySet keyframeProperties = keyframe->properties(); |
145 for (PropertySet::const_iterator propertyIter = keyframeProperties.begin
(); propertyIter != keyframeProperties.end(); ++propertyIter) { | 204 for (PropertySet::const_iterator propertyIter = keyframeProperties.begin
(); propertyIter != keyframeProperties.end(); ++propertyIter) { |
146 CSSPropertyID property = *propertyIter; | 205 CSSPropertyID property = *propertyIter; |
147 KeyframeGroupMap::iterator groupIter = m_keyframeGroups->find(proper
ty); | 206 KeyframeGroupMap::iterator groupIter = m_keyframeGroups->find(proper
ty); |
148 PropertySpecificKeyframeGroup* group; | 207 PropertySpecificKeyframeGroup* group; |
149 if (groupIter == m_keyframeGroups->end()) | 208 if (groupIter == m_keyframeGroups->end()) |
150 group = m_keyframeGroups->add(property, adoptPtrWillBeNoop(new P
ropertySpecificKeyframeGroup)).storedValue->value.get(); | 209 group = m_keyframeGroups->add(property, adoptPtrWillBeNoop(new P
ropertySpecificKeyframeGroup)).storedValue->value.get(); |
151 else | 210 else |
152 group = groupIter->value.get(); | 211 group = groupIter->value.get(); |
153 | 212 |
154 ASSERT(keyframe->composite() == AnimationEffect::CompositeReplace); | 213 ASSERT(keyframe->composite() == AnimationEffect::CompositeReplace); |
155 group->appendKeyframe(keyframe->createPropertySpecificKeyframe(prope
rty)); | 214 group->appendKeyframe(adoptPtrWillBeNoop( |
| 215 new PropertySpecificKeyframe(keyframe->offset(), keyframe->easin
g(), keyframe->propertyValue(property), keyframe->composite()))); |
156 } | 216 } |
157 } | 217 } |
158 | 218 |
159 // Add synthetic keyframes. | 219 // Add synthetic keyframes. |
160 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { | 220 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { |
161 iter->value->addSyntheticKeyframeIfRequired(this); | 221 iter->value->addSyntheticKeyframeIfRequired(); |
162 iter->value->removeRedundantKeyframes(); | 222 iter->value->removeRedundantKeyframes(); |
163 } | 223 } |
164 } | 224 } |
165 | 225 |
166 void KeyframeEffectModelBase::ensureInterpolationEffect() const | 226 void KeyframeEffectModel::ensureInterpolationEffect() const |
167 { | 227 { |
168 if (m_interpolationEffect) | 228 if (m_interpolationEffect) |
169 return; | 229 return; |
170 m_interpolationEffect = InterpolationEffect::create(); | 230 m_interpolationEffect = InterpolationEffect::create(); |
171 | 231 |
172 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter
!= m_keyframeGroups->end(); ++iter) { | 232 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter
!= m_keyframeGroups->end(); ++iter) { |
173 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes
(); | 233 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes
(); |
174 ASSERT(keyframes[0]->composite() == AnimationEffect::CompositeReplace); | 234 ASSERT(keyframes[0]->composite() == AnimationEffect::CompositeReplace); |
| 235 const AnimatableValue* start; |
| 236 const AnimatableValue* end = keyframes[0]->value(); |
175 for (size_t i = 0; i < keyframes.size() - 1; i++) { | 237 for (size_t i = 0; i < keyframes.size() - 1; i++) { |
176 ASSERT(keyframes[i + 1]->composite() == AnimationEffect::CompositeRe
place); | 238 ASSERT(keyframes[i + 1]->composite() == AnimationEffect::CompositeRe
place); |
| 239 start = end; |
| 240 end = keyframes[i + 1]->value(); |
177 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit
s<double>::infinity()); | 241 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit
s<double>::infinity()); |
178 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou
ble>::infinity() : keyframes[i + 1]->offset(); | 242 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou
ble>::infinity() : keyframes[i + 1]->offset(); |
179 if (applyTo == 1) | 243 if (applyTo == 1) |
180 applyTo = std::numeric_limits<double>::infinity(); | 244 applyTo = std::numeric_limits<double>::infinity(); |
181 | 245 m_interpolationEffect->addInterpolation( |
182 m_interpolationEffect->addInterpolation(keyframes[i]->createInterpol
ation(iter->key, keyframes[i + 1].get()), | 246 LegacyStyleInterpolation::create( |
| 247 AnimatableValue::takeConstRef(start), |
| 248 AnimatableValue::takeConstRef(end), iter->key), |
183 keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i + 1]
->offset(), applyFrom, applyTo); | 249 keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i + 1]
->offset(), applyFrom, applyTo); |
184 } | 250 } |
185 } | 251 } |
186 } | 252 } |
187 | 253 |
188 bool KeyframeEffectModelBase::isReplaceOnly() | 254 bool KeyframeEffectModel::isReplaceOnly() |
189 { | 255 { |
190 ensureKeyframeGroups(); | 256 ensureKeyframeGroups(); |
191 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { | 257 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { |
192 const PropertySpecificKeyframeVector& keyframeVector = iter->value->keyf
rames(); | 258 const PropertySpecificKeyframeVector& keyframeVector = iter->value->keyf
rames(); |
193 for (size_t i = 0; i < keyframeVector.size(); ++i) { | 259 for (size_t i = 0; i < keyframeVector.size(); ++i) { |
194 if (keyframeVector[i]->composite() != AnimationEffect::CompositeRepl
ace) | 260 if (keyframeVector[i]->composite() != AnimationEffect::CompositeRepl
ace) |
195 return false; | 261 return false; |
196 } | 262 } |
197 } | 263 } |
198 return true; | 264 return true; |
199 } | 265 } |
200 | 266 |
201 void KeyframeEffectModelBase::trace(Visitor* visitor) | 267 void KeyframeEffectModel::trace(Visitor* visitor) |
202 { | 268 { |
203 visitor->trace(m_keyframes); | 269 visitor->trace(m_keyframes); |
204 visitor->trace(m_interpolationEffect); | 270 visitor->trace(m_interpolationEffect); |
205 #if ENABLE_OILPAN | 271 #if ENABLE_OILPAN |
206 visitor->trace(m_keyframeGroups); | 272 visitor->trace(m_keyframeGroups); |
207 #endif | 273 #endif |
208 } | 274 } |
209 | 275 |
210 Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, Pass
RefPtr<TimingFunction> easing, AnimationEffect::CompositeOperation composite) | 276 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o
ffset, PassRefPtr<TimingFunction> easing, const AnimatableValue* value, Composit
eOperation composite) |
211 : m_offset(offset) | 277 : m_offset(offset) |
212 , m_easing(easing) | 278 , m_easing(easing) |
213 , m_composite(composite) | 279 , m_composite(composite) |
214 { | 280 { |
| 281 m_value = AnimatableValue::takeConstRef(value); |
215 } | 282 } |
216 | 283 |
217 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::appendKeyframe(Pass
OwnPtr<PropertySpecificKeyframe> keyframe) | 284 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o
ffset, PassRefPtr<TimingFunction> easing, PassRefPtrWillBeRawPtr<AnimatableValue
> value, CompositeOperation composite) |
| 285 : m_offset(offset) |
| 286 , m_easing(easing) |
| 287 , m_value(value) |
| 288 , m_composite(composite) |
| 289 { |
| 290 ASSERT(!isNull(m_offset)); |
| 291 } |
| 292 |
| 293 PassOwnPtrWillBeRawPtr<KeyframeEffectModel::PropertySpecificKeyframe> KeyframeEf
fectModel::PropertySpecificKeyframe::cloneWithOffset(double offset) const |
| 294 { |
| 295 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, m_easing, m_v
alue.get(), m_composite)); |
| 296 } |
| 297 |
| 298 void KeyframeEffectModel::PropertySpecificKeyframe::trace(Visitor* visitor) |
| 299 { |
| 300 visitor->trace(m_value); |
| 301 } |
| 302 |
| 303 void KeyframeEffectModel::PropertySpecificKeyframeGroup::appendKeyframe(PassOwnP
trWillBeRawPtr<PropertySpecificKeyframe> keyframe) |
218 { | 304 { |
219 ASSERT(m_keyframes.isEmpty() || m_keyframes.last()->offset() <= keyframe->of
fset()); | 305 ASSERT(m_keyframes.isEmpty() || m_keyframes.last()->offset() <= keyframe->of
fset()); |
220 m_keyframes.append(keyframe); | 306 m_keyframes.append(keyframe); |
221 } | 307 } |
222 | 308 |
223 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::removeRedundantKeyf
rames() | 309 void KeyframeEffectModel::PropertySpecificKeyframeGroup::removeRedundantKeyframe
s() |
224 { | 310 { |
225 // As an optimization, removes keyframes in the following categories, as | 311 // As an optimization, removes keyframes in the following categories, as |
226 // they will never be used by sample(). | 312 // they will never be used by sample(). |
227 // - End keyframes with the same offset as their neighbor | 313 // - End keyframes with the same offset as their neighbor |
228 // - Interior keyframes with the same offset as both their neighbors | 314 // - Interior keyframes with the same offset as both their neighbors |
229 // Note that synthetic keyframes must be added before this method is | 315 // Note that synthetic keyframes must be added before this method is |
230 // called. | 316 // called. |
231 ASSERT(m_keyframes.size() >= 2); | 317 ASSERT(m_keyframes.size() >= 2); |
232 for (int i = m_keyframes.size() - 1; i >= 0; --i) { | 318 for (int i = m_keyframes.size() - 1; i >= 0; --i) { |
233 double offset = m_keyframes[i]->offset(); | 319 double offset = m_keyframes[i]->offset(); |
234 bool hasSameOffsetAsPreviousNeighbor = !i || m_keyframes[i - 1]->offset(
) == offset; | 320 bool hasSameOffsetAsPreviousNeighbor = !i || m_keyframes[i - 1]->offset(
) == offset; |
235 bool hasSameOffsetAsNextNeighbor = i == static_cast<int>(m_keyframes.siz
e() - 1) || m_keyframes[i + 1]->offset() == offset; | 321 bool hasSameOffsetAsNextNeighbor = i == static_cast<int>(m_keyframes.siz
e() - 1) || m_keyframes[i + 1]->offset() == offset; |
236 if (hasSameOffsetAsPreviousNeighbor && hasSameOffsetAsNextNeighbor) | 322 if (hasSameOffsetAsPreviousNeighbor && hasSameOffsetAsNextNeighbor) |
237 m_keyframes.remove(i); | 323 m_keyframes.remove(i); |
238 } | 324 } |
239 ASSERT(m_keyframes.size() >= 2); | 325 ASSERT(m_keyframes.size() >= 2); |
240 } | 326 } |
241 | 327 |
242 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::addSyntheticKeyfram
eIfRequired(const KeyframeEffectModelBase* context) | 328 void KeyframeEffectModel::PropertySpecificKeyframeGroup::addSyntheticKeyframeIfR
equired() |
243 { | 329 { |
244 ASSERT(!m_keyframes.isEmpty()); | 330 ASSERT(!m_keyframes.isEmpty()); |
245 if (m_keyframes.first()->offset() != 0.0) | 331 if (m_keyframes.first()->offset() != 0.0) |
246 m_keyframes.insert(0, m_keyframes.first()->neutralKeyframe(0, nullptr)); | 332 m_keyframes.insert(0, adoptPtrWillBeNoop(new PropertySpecificKeyframe(0,
nullptr, AnimatableValue::neutralValue(), CompositeAdd))); |
247 if (m_keyframes.last()->offset() != 1.0) | 333 if (m_keyframes.last()->offset() != 1.0) |
248 appendKeyframe(m_keyframes.last()->neutralKeyframe(1, nullptr)); | 334 appendKeyframe(adoptPtrWillBeNoop(new PropertySpecificKeyframe(1, nullpt
r, AnimatableValue::neutralValue(), CompositeAdd))); |
249 } | 335 } |
250 | 336 |
251 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::trace(Visitor* visi
tor) | 337 void KeyframeEffectModel::PropertySpecificKeyframeGroup::trace(Visitor* visitor) |
252 { | 338 { |
253 #if ENABLE(OILPAN) | 339 #if ENABLE_OILPAN |
254 visitor->trace(m_keyframes); | 340 visitor->trace(m_keyframes); |
255 #endif | 341 #endif |
256 } | 342 } |
257 | 343 |
258 template <> | |
259 bool KeyframeEffectModel<AnimatableValueKeyframe>::isAnimatableValueKeyframeEffe
ctModel() const { return true; } | |
260 | |
261 template <> | |
262 bool KeyframeEffectModel<StringKeyframe>::isStringKeyframeEffectModel() const {
return true; } | |
263 | |
264 } // namespace | 344 } // namespace |
OLD | NEW |