| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 #include "sky/engine/core/animation/KeyframeEffectModel.h" | |
| 32 | |
| 33 #include "gen/sky/core/StylePropertyShorthand.h" | |
| 34 #include "sky/engine/core/animation/AnimationNode.h" | |
| 35 #include "sky/engine/platform/geometry/FloatBox.h" | |
| 36 #include "sky/engine/platform/transforms/TransformationMatrix.h" | |
| 37 #include "sky/engine/wtf/text/StringHash.h" | |
| 38 | |
| 39 namespace blink { | |
| 40 | |
| 41 PropertySet KeyframeEffectModelBase::properties() const | |
| 42 { | |
| 43 PropertySet result; | |
| 44 if (!m_keyframes.size()) { | |
| 45 return result; | |
| 46 } | |
| 47 result = m_keyframes[0]->properties(); | |
| 48 for (size_t i = 1; i < m_keyframes.size(); i++) { | |
| 49 PropertySet extras = m_keyframes[i]->properties(); | |
| 50 for (PropertySet::const_iterator it = extras.begin(); it != extras.end()
; ++it) { | |
| 51 result.add(*it); | |
| 52 } | |
| 53 } | |
| 54 return result; | |
| 55 } | |
| 56 | |
| 57 PassOwnPtr<Vector<RefPtr<Interpolation> > > KeyframeEffectModelBase::sample(int
iteration, double fraction, double iterationDuration) const | |
| 58 { | |
| 59 ASSERT(iteration >= 0); | |
| 60 ASSERT(!isNull(fraction)); | |
| 61 ensureKeyframeGroups(); | |
| 62 ensureInterpolationEffect(); | |
| 63 | |
| 64 return m_interpolationEffect->getActiveInterpolations(fraction, iterationDur
ation); | |
| 65 } | |
| 66 | |
| 67 KeyframeEffectModelBase::KeyframeVector KeyframeEffectModelBase::normalizedKeyfr
ames(const KeyframeVector& keyframes) | |
| 68 { | |
| 69 double lastOffset = 0; | |
| 70 KeyframeVector result; | |
| 71 result.reserveCapacity(keyframes.size()); | |
| 72 | |
| 73 for (size_t i = 0; i < keyframes.size(); ++i) { | |
| 74 double offset = keyframes[i]->offset(); | |
| 75 if (!isNull(offset)) { | |
| 76 ASSERT(offset >= 0); | |
| 77 ASSERT(offset <= 1); | |
| 78 ASSERT(offset >= lastOffset); | |
| 79 lastOffset = offset; | |
| 80 } | |
| 81 result.append(keyframes[i]->clone()); | |
| 82 } | |
| 83 | |
| 84 if (result.isEmpty()) { | |
| 85 return result; | |
| 86 } | |
| 87 | |
| 88 if (isNull(result.last()->offset())) | |
| 89 result.last()->setOffset(1); | |
| 90 | |
| 91 if (result.size() > 1 && isNull(result[0]->offset())) | |
| 92 result[0]->setOffset(0); | |
| 93 | |
| 94 size_t lastIndex = 0; | |
| 95 lastOffset = result[0]->offset(); | |
| 96 for (size_t i = 1; i < result.size(); ++i) { | |
| 97 double offset = result[i]->offset(); | |
| 98 if (!isNull(offset)) { | |
| 99 for (size_t j = 1; j < i - lastIndex; ++j) | |
| 100 result[lastIndex + j]->setOffset(lastOffset + (offset - lastOffs
et) * j / (i - lastIndex)); | |
| 101 lastIndex = i; | |
| 102 lastOffset = offset; | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 return result; | |
| 107 } | |
| 108 | |
| 109 | |
| 110 void KeyframeEffectModelBase::ensureKeyframeGroups() const | |
| 111 { | |
| 112 if (m_keyframeGroups) | |
| 113 return; | |
| 114 | |
| 115 m_keyframeGroups = adoptPtr(new KeyframeGroupMap); | |
| 116 const KeyframeVector keyframes = normalizedKeyframes(getFrames()); | |
| 117 for (KeyframeVector::const_iterator keyframeIter = keyframes.begin(); keyfra
meIter != keyframes.end(); ++keyframeIter) { | |
| 118 const Keyframe* keyframe = keyframeIter->get(); | |
| 119 PropertySet keyframeProperties = keyframe->properties(); | |
| 120 for (PropertySet::const_iterator propertyIter = keyframeProperties.begin
(); propertyIter != keyframeProperties.end(); ++propertyIter) { | |
| 121 CSSPropertyID property = *propertyIter; | |
| 122 ASSERT_WITH_MESSAGE(!isExpandedShorthand(property), "Web Animations:
Encountered shorthand CSS property (%d) in normalized keyframes.", property); | |
| 123 KeyframeGroupMap::iterator groupIter = m_keyframeGroups->find(proper
ty); | |
| 124 PropertySpecificKeyframeGroup* group; | |
| 125 if (groupIter == m_keyframeGroups->end()) | |
| 126 group = m_keyframeGroups->add(property, adoptPtr(new PropertySpe
cificKeyframeGroup)).storedValue->value.get(); | |
| 127 else | |
| 128 group = groupIter->value.get(); | |
| 129 | |
| 130 group->appendKeyframe(keyframe->createPropertySpecificKeyframe(prope
rty)); | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 // Add synthetic keyframes. | |
| 135 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { | |
| 136 iter->value->addSyntheticKeyframeIfRequired(this); | |
| 137 iter->value->removeRedundantKeyframes(); | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 void KeyframeEffectModelBase::ensureInterpolationEffect(Element* element) const | |
| 142 { | |
| 143 if (m_interpolationEffect) | |
| 144 return; | |
| 145 m_interpolationEffect = InterpolationEffect::create(); | |
| 146 | |
| 147 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter
!= m_keyframeGroups->end(); ++iter) { | |
| 148 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes
(); | |
| 149 ASSERT(keyframes[0]->composite() == AnimationEffect::CompositeReplace); | |
| 150 for (size_t i = 0; i < keyframes.size() - 1; i++) { | |
| 151 ASSERT(keyframes[i + 1]->composite() == AnimationEffect::CompositeRe
place); | |
| 152 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit
s<double>::infinity()); | |
| 153 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou
ble>::infinity() : keyframes[i + 1]->offset(); | |
| 154 if (applyTo == 1) | |
| 155 applyTo = std::numeric_limits<double>::infinity(); | |
| 156 | |
| 157 m_interpolationEffect->addInterpolation(keyframes[i]->createInterpol
ation(iter->key, keyframes[i + 1].get(), element), | |
| 158 &keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i + 1
]->offset(), applyFrom, applyTo); | |
| 159 } | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 bool KeyframeEffectModelBase::isReplaceOnly() | |
| 164 { | |
| 165 ensureKeyframeGroups(); | |
| 166 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_
keyframeGroups->end(); ++iter) { | |
| 167 const PropertySpecificKeyframeVector& keyframeVector = iter->value->keyf
rames(); | |
| 168 for (size_t i = 0; i < keyframeVector.size(); ++i) { | |
| 169 if (keyframeVector[i]->composite() != AnimationEffect::CompositeRepl
ace) | |
| 170 return false; | |
| 171 } | |
| 172 } | |
| 173 return true; | |
| 174 } | |
| 175 | |
| 176 Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, Pass
RefPtr<TimingFunction> easing, AnimationEffect::CompositeOperation composite) | |
| 177 : m_offset(offset) | |
| 178 , m_easing(easing) | |
| 179 , m_composite(composite) | |
| 180 { | |
| 181 } | |
| 182 | |
| 183 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::appendKeyframe(Pass
OwnPtr<Keyframe::PropertySpecificKeyframe> keyframe) | |
| 184 { | |
| 185 ASSERT(m_keyframes.isEmpty() || m_keyframes.last()->offset() <= keyframe->of
fset()); | |
| 186 m_keyframes.append(keyframe); | |
| 187 } | |
| 188 | |
| 189 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::removeRedundantKeyf
rames() | |
| 190 { | |
| 191 // As an optimization, removes keyframes in the following categories, as | |
| 192 // they will never be used by sample(). | |
| 193 // - End keyframes with the same offset as their neighbor | |
| 194 // - Interior keyframes with the same offset as both their neighbors | |
| 195 // Note that synthetic keyframes must be added before this method is | |
| 196 // called. | |
| 197 ASSERT(m_keyframes.size() >= 2); | |
| 198 for (int i = m_keyframes.size() - 1; i >= 0; --i) { | |
| 199 double offset = m_keyframes[i]->offset(); | |
| 200 bool hasSameOffsetAsPreviousNeighbor = !i || m_keyframes[i - 1]->offset(
) == offset; | |
| 201 bool hasSameOffsetAsNextNeighbor = i == static_cast<int>(m_keyframes.siz
e() - 1) || m_keyframes[i + 1]->offset() == offset; | |
| 202 if (hasSameOffsetAsPreviousNeighbor && hasSameOffsetAsNextNeighbor) | |
| 203 m_keyframes.remove(i); | |
| 204 } | |
| 205 ASSERT(m_keyframes.size() >= 2); | |
| 206 } | |
| 207 | |
| 208 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::addSyntheticKeyfram
eIfRequired(const KeyframeEffectModelBase* context) | |
| 209 { | |
| 210 ASSERT(!m_keyframes.isEmpty()); | |
| 211 if (m_keyframes.first()->offset() != 0.0) | |
| 212 m_keyframes.insert(0, m_keyframes.first()->neutralKeyframe(0, nullptr)); | |
| 213 if (m_keyframes.last()->offset() != 1.0) | |
| 214 appendKeyframe(m_keyframes.last()->neutralKeyframe(1, nullptr)); | |
| 215 } | |
| 216 | |
| 217 } // namespace | |
| OLD | NEW |