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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 , m_after(const_cast<AnimationEffect::CompositableValue*>(after)) | 80 , m_after(const_cast<AnimationEffect::CompositableValue*>(after)) |
81 , m_fraction(fraction) | 81 , m_fraction(fraction) |
82 , m_dependsOnUnderlyingValue(before->dependsOnUnderlyingValue() || after
->dependsOnUnderlyingValue()) | 82 , m_dependsOnUnderlyingValue(before->dependsOnUnderlyingValue() || after
->dependsOnUnderlyingValue()) |
83 { } | 83 { } |
84 RefPtr<AnimationEffect::CompositableValue> m_before; | 84 RefPtr<AnimationEffect::CompositableValue> m_before; |
85 RefPtr<AnimationEffect::CompositableValue> m_after; | 85 RefPtr<AnimationEffect::CompositableValue> m_after; |
86 double m_fraction; | 86 double m_fraction; |
87 bool m_dependsOnUnderlyingValue; | 87 bool m_dependsOnUnderlyingValue; |
88 }; | 88 }; |
89 | 89 |
90 const double accuracyForKeyframeEasing = 0.0000001; | |
91 | |
92 } // namespace | 90 } // namespace |
93 | 91 |
94 | 92 |
95 namespace WebCore { | 93 namespace WebCore { |
96 | 94 |
97 Keyframe::Keyframe() | 95 Keyframe::Keyframe() |
98 : m_offset(nullValue()) | 96 : m_offset(nullValue()) |
99 , m_composite(AnimationEffect::CompositeReplace) | 97 , m_composite(AnimationEffect::CompositeReplace) |
100 , m_easing(LinearTimingFunction::preset()) | 98 , m_easing(LinearTimingFunction::preset()) |
101 { } | 99 { } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 result = m_keyframes[0]->properties(); | 161 result = m_keyframes[0]->properties(); |
164 for (size_t i = 1; i < m_keyframes.size(); i++) { | 162 for (size_t i = 1; i < m_keyframes.size(); i++) { |
165 PropertySet extras = m_keyframes[i]->properties(); | 163 PropertySet extras = m_keyframes[i]->properties(); |
166 for (PropertySet::const_iterator it = extras.begin(); it != extras.end()
; ++it) { | 164 for (PropertySet::const_iterator it = extras.begin(); it != extras.end()
; ++it) { |
167 result.add(*it); | 165 result.add(*it); |
168 } | 166 } |
169 } | 167 } |
170 return result; | 168 return result; |
171 } | 169 } |
172 | 170 |
173 PassOwnPtr<AnimationEffect::CompositableValueList> KeyframeEffectModel::sample(i
nt iteration, double fraction) const | 171 PassOwnPtr<Vector<RefPtr<Interpolation> > > KeyframeEffectModel::sample(int iter
ation, double fraction) const |
174 { | 172 { |
175 ASSERT(iteration >= 0); | 173 ASSERT(iteration >= 0); |
176 ASSERT(!isNull(fraction)); | 174 ASSERT(!isNull(fraction)); |
177 const_cast<KeyframeEffectModel*>(this)->ensureKeyframeGroups(); | 175 ensureKeyframeGroups(); |
178 OwnPtr<CompositableValueList> map = adoptPtr(new CompositableValueList()); | 176 ensureInterpolationEffect(); |
179 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter
!= m_keyframeGroups->end(); ++iter) | 177 |
180 map->append(std::make_pair(iter->key, iter->value->sample(iteration, fra
ction))); | 178 return m_interpolationEffect->getActiveInterpolations(fraction); |
181 return map.release(); | |
182 } | 179 } |
183 | 180 |
184 KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(con
st KeyframeVector& keyframes) | 181 KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(con
st KeyframeVector& keyframes) |
185 { | 182 { |
186 // keyframes [beginIndex, endIndex) will remain after removing all keyframes
if they are not | 183 // keyframes [beginIndex, endIndex) will remain after removing all keyframes
if they are not |
187 // loosely sorted by offset, and after removing keyframes with positional of
fset outide [0, 1]. | 184 // loosely sorted by offset, and after removing keyframes with positional of
fset outide [0, 1]. |
188 size_t beginIndex = 0; | 185 size_t beginIndex = 0; |
189 size_t endIndex = keyframes.size(); | 186 size_t endIndex = keyframes.size(); |
190 | 187 |
191 // Becomes the most recent keyframe with an explicit offset. | 188 // Becomes the most recent keyframe with an explicit offset. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 } | 266 } |
270 } | 267 } |
271 | 268 |
272 // Add synthetic keyframes. | 269 // Add synthetic keyframes. |
273 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { | 270 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { |
274 iter->value->addSyntheticKeyframeIfRequired(); | 271 iter->value->addSyntheticKeyframeIfRequired(); |
275 iter->value->removeRedundantKeyframes(); | 272 iter->value->removeRedundantKeyframes(); |
276 } | 273 } |
277 } | 274 } |
278 | 275 |
| 276 void KeyframeEffectModel::ensureInterpolationEffect() const |
| 277 { |
| 278 if (m_interpolationEffect) |
| 279 return; |
| 280 m_interpolationEffect = InterpolationEffect::create(); |
| 281 |
| 282 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter
!= m_keyframeGroups->end(); ++iter) { |
| 283 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes
(); |
| 284 ASSERT(keyframes[0]->value()->isAnimatableValue()); |
| 285 const AnimatableValue* start; |
| 286 const AnimatableValue* end = toAnimatableValue(keyframes[0]->value()); |
| 287 for (size_t i = 0; i < keyframes.size() - 1; i++) { |
| 288 ASSERT(keyframes[i + 1]->value()->isAnimatableValue()); |
| 289 start = end; |
| 290 end = toAnimatableValue(keyframes[i + 1]->value()); |
| 291 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit
s<double>::infinity()); |
| 292 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou
ble>::infinity() : keyframes[i+1]->offset(); |
| 293 if (applyTo == 1) |
| 294 applyTo = std::numeric_limits<double>::infinity(); |
| 295 m_interpolationEffect->addInterpolation( |
| 296 LegacyStyleInterpolation::create( |
| 297 AnimatableValue::takeConstRef(start), |
| 298 AnimatableValue::takeConstRef(end), iter->key), |
| 299 keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i+1]->
offset(), applyFrom, applyTo); |
| 300 } |
| 301 } |
| 302 } |
279 | 303 |
280 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o
ffset, PassRefPtr<TimingFunction> easing, const AnimatableValue* value, Composit
eOperation composite) | 304 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o
ffset, PassRefPtr<TimingFunction> easing, const AnimatableValue* value, Composit
eOperation composite) |
281 : m_offset(offset) | 305 : m_offset(offset) |
282 , m_easing(easing) | 306 , m_easing(easing) |
283 , m_value(composite == AnimationEffect::CompositeReplace ? | 307 , m_value(composite == AnimationEffect::CompositeReplace ? |
284 AnimatableValue::takeConstRef(value) : | 308 AnimatableValue::takeConstRef(value) : |
285 static_cast<PassRefPtr<CompositableValue> >(AddCompositableValue::create
(value))) | 309 static_cast<PassRefPtr<CompositableValue> >(AddCompositableValue::create
(value))) |
286 { | 310 { |
287 } | 311 } |
288 | 312 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 } | 362 } |
339 if (!allOffsetsEqual) | 363 if (!allOffsetsEqual) |
340 return; | 364 return; |
341 | 365 |
342 if (!offset) | 366 if (!offset) |
343 appendKeyframe(m_keyframes.first()->cloneWithOffset(1.0)); | 367 appendKeyframe(m_keyframes.first()->cloneWithOffset(1.0)); |
344 else | 368 else |
345 m_keyframes.insert(0, adoptPtr(new PropertySpecificKeyframe(0.0, nullptr
, AnimatableValue::neutralValue(), CompositeAdd))); | 369 m_keyframes.insert(0, adoptPtr(new PropertySpecificKeyframe(0.0, nullptr
, AnimatableValue::neutralValue(), CompositeAdd))); |
346 } | 370 } |
347 | 371 |
348 PassRefPtr<AnimationEffect::CompositableValue> KeyframeEffectModel::PropertySpec
ificKeyframeGroup::sample(int iteration, double offset) const | |
349 { | |
350 // FIXME: Implement accumulation. | |
351 ASSERT_UNUSED(iteration, iteration >= 0); | |
352 ASSERT(!isNull(offset)); | |
353 | |
354 // Bail if offset is null, as this can lead to buffer overflow below. | |
355 if (isNull(offset)) | |
356 return const_cast<CompositableValue*>(m_keyframes.first()->value()); | |
357 | |
358 double minimumOffset = m_keyframes.first()->offset(); | |
359 double maximumOffset = m_keyframes.last()->offset(); | |
360 ASSERT(minimumOffset != maximumOffset); | |
361 | |
362 PropertySpecificKeyframeVector::const_iterator before; | |
363 PropertySpecificKeyframeVector::const_iterator after; | |
364 | |
365 // Note that this algorithm is simpler than that in the spec because we | |
366 // have removed keyframes with equal offsets in | |
367 // removeRedundantKeyframes(). | |
368 if (offset < minimumOffset) { | |
369 before = m_keyframes.begin(); | |
370 after = before + 1; | |
371 ASSERT((*before)->offset() > offset); | |
372 ASSERT((*after)->offset() > offset); | |
373 } else if (offset >= maximumOffset) { | |
374 after = m_keyframes.end() - 1; | |
375 before = after - 1; | |
376 ASSERT((*before)->offset() < offset); | |
377 ASSERT((*after)->offset() <= offset); | |
378 } else { | |
379 // FIXME: This is inefficient for large numbers of keyframes. Consider | |
380 // using binary search. | |
381 after = m_keyframes.begin(); | |
382 while ((*after)->offset() <= offset) | |
383 ++after; | |
384 before = after - 1; | |
385 ASSERT((*before)->offset() <= offset); | |
386 ASSERT((*after)->offset() > offset); | |
387 } | |
388 | |
389 if ((*before)->offset() == offset) | |
390 return const_cast<CompositableValue*>((*before)->value()); | |
391 if ((*after)->offset() == offset) | |
392 return const_cast<CompositableValue*>((*after)->value()); | |
393 | |
394 double fraction = (offset - (*before)->offset()) / ((*after)->offset() - (*b
efore)->offset()); | |
395 if (const TimingFunction* timingFunction = (*before)->easing()) | |
396 fraction = timingFunction->evaluate(fraction, accuracyForKeyframeEasing)
; | |
397 return BlendedCompositableValue::create((*before)->value(), (*after)->value(
), fraction); | |
398 } | |
399 | |
400 void KeyframeEffectModel::trace(Visitor* visitor) | 372 void KeyframeEffectModel::trace(Visitor* visitor) |
401 { | 373 { |
402 visitor->trace(m_keyframes); | 374 visitor->trace(m_keyframes); |
403 } | 375 } |
404 | 376 |
405 } // namespace | 377 } // namespace |
OLD | NEW |