OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/animation/StringKeyframe.h" | 6 #include "core/animation/InterpolationFactory.h" |
7 | 7 |
8 #include "core/animation/ColorStyleInterpolation.h" | 8 #include "core/animation/ColorStyleInterpolation.h" |
9 #include "core/animation/ConstantStyleInterpolation.h" | 9 #include "core/animation/ConstantStyleInterpolation.h" |
10 #include "core/animation/DeferredLegacyStyleInterpolation.h" | 10 #include "core/animation/DeferredLegacyStyleInterpolation.h" |
11 #include "core/animation/DoubleStyleInterpolation.h" | 11 #include "core/animation/DoubleStyleInterpolation.h" |
12 #include "core/animation/ImageStyleInterpolation.h" | 12 #include "core/animation/ImageStyleInterpolation.h" |
13 #include "core/animation/LegacyStyleInterpolation.h" | 13 #include "core/animation/LegacyStyleInterpolation.h" |
14 #include "core/animation/LengthBoxStyleInterpolation.h" | 14 #include "core/animation/LengthBoxStyleInterpolation.h" |
15 #include "core/animation/LengthPairStyleInterpolation.h" | 15 #include "core/animation/LengthPairStyleInterpolation.h" |
16 #include "core/animation/LengthStyleInterpolation.h" | 16 #include "core/animation/LengthStyleInterpolation.h" |
17 #include "core/animation/ListStyleInterpolation.h" | 17 #include "core/animation/ListStyleInterpolation.h" |
18 #include "core/animation/SVGLengthStyleInterpolation.h" | 18 #include "core/animation/SVGLengthStyleInterpolation.h" |
19 #include "core/animation/ShadowStyleInterpolation.h" | 19 #include "core/animation/ShadowStyleInterpolation.h" |
20 #include "core/animation/VisibilityStyleInterpolation.h" | 20 #include "core/animation/VisibilityStyleInterpolation.h" |
21 #include "core/animation/css/CSSAnimations.h" | |
22 #include "core/css/CSSPropertyMetadata.h" | 21 #include "core/css/CSSPropertyMetadata.h" |
23 #include "core/css/resolver/StyleResolver.h" | 22 #include "core/css/resolver/StyleResolver.h" |
24 #include "core/layout/style/LayoutStyle.h" | |
25 | 23 |
26 namespace blink { | 24 namespace blink { |
27 | 25 |
28 StringKeyframe::StringKeyframe(const StringKeyframe& copyFrom) | 26 static InterpolationRange setRange(CSSPropertyID id) |
29 : Keyframe(copyFrom.m_offset, copyFrom.m_composite, copyFrom.m_easing) | |
30 , m_propertySet(copyFrom.m_propertySet->mutableCopy()) | |
31 { | |
32 } | |
33 | |
34 void StringKeyframe::setPropertyValue(CSSPropertyID property, const String& valu
e, StyleSheetContents* styleSheetContents) | |
35 { | |
36 ASSERT(property != CSSPropertyInvalid); | |
37 if (CSSAnimations::isAllowedAnimation(property)) | |
38 m_propertySet->setProperty(property, value, false, styleSheetContents); | |
39 } | |
40 | |
41 PropertySet StringKeyframe::properties() const | |
42 { | |
43 // This is not used in time-critical code, so we probably don't need to | |
44 // worry about caching this result. | |
45 PropertySet properties; | |
46 for (unsigned i = 0; i < m_propertySet->propertyCount(); ++i) | |
47 properties.add(m_propertySet->propertyAt(i).id()); | |
48 return properties; | |
49 } | |
50 | |
51 PassRefPtrWillBeRawPtr<Keyframe> StringKeyframe::clone() const | |
52 { | |
53 return adoptRefWillBeNoop(new StringKeyframe(*this)); | |
54 } | |
55 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::creat
ePropertySpecificKeyframe(CSSPropertyID property) const | |
56 { | |
57 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset(), &easing(),
propertyValue(property), composite())); | |
58 } | |
59 | |
60 void StringKeyframe::trace(Visitor* visitor) | |
61 { | |
62 visitor->trace(m_propertySet); | |
63 Keyframe::trace(visitor); | |
64 } | |
65 | |
66 StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset
, PassRefPtr<TimingFunction> easing, CSSValue* value, AnimationEffect::Composite
Operation op) | |
67 : Keyframe::PropertySpecificKeyframe(offset, easing, op) | |
68 , m_value(value) | |
69 { } | |
70 | |
71 StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset
, PassRefPtr<TimingFunction> easing, CSSValue* value) | |
72 : Keyframe::PropertySpecificKeyframe(offset, easing, AnimationEffect::Compos
iteReplace) | |
73 , m_value(value) | |
74 { | |
75 ASSERT(!isNull(m_offset)); | |
76 } | |
77 | |
78 namespace { | |
79 InterpolationRange setRange(CSSPropertyID id) | |
80 { | 27 { |
81 switch (id) { | 28 switch (id) { |
82 case CSSPropertyOrphans: | 29 case CSSPropertyOrphans: |
83 case CSSPropertyWebkitColumnCount: | 30 case CSSPropertyWebkitColumnCount: |
84 case CSSPropertyWidows: | 31 case CSSPropertyWidows: |
85 return RangeRoundGreaterThanOrEqualToOne; | 32 return RangeRoundGreaterThanOrEqualToOne; |
86 case CSSPropertyWebkitColumnRuleWidth: | 33 case CSSPropertyWebkitColumnRuleWidth: |
87 case CSSPropertyZIndex: | 34 case CSSPropertyZIndex: |
88 return RangeRound; | 35 return RangeRound; |
89 case CSSPropertyFloodOpacity: | 36 case CSSPropertyFloodOpacity: |
90 case CSSPropertyStopOpacity: | 37 case CSSPropertyStopOpacity: |
91 case CSSPropertyStrokeOpacity: | 38 case CSSPropertyStrokeOpacity: |
92 case CSSPropertyShapeImageThreshold: | 39 case CSSPropertyShapeImageThreshold: |
93 return RangeZeroToOne; | 40 return RangeZeroToOne; |
94 case CSSPropertyFillOpacity: | 41 case CSSPropertyFillOpacity: |
95 case CSSPropertyOpacity: | 42 case CSSPropertyOpacity: |
96 return RangeOpacityFIXME; | 43 return RangeOpacityFIXME; |
97 case CSSPropertyStrokeMiterlimit: | 44 case CSSPropertyStrokeMiterlimit: |
98 return RangeGreaterThanOrEqualToOne; | 45 return RangeGreaterThanOrEqualToOne; |
99 case CSSPropertyZoom: | 46 case CSSPropertyZoom: |
100 return RangePositive; | 47 return RangePositive; |
101 default: | 48 default: |
102 ASSERT_NOT_REACHED(); | 49 ASSERT_NOT_REACHED(); |
103 return RangeAll; | 50 return RangeAll; |
104 } | 51 } |
105 } | 52 } |
106 | 53 |
107 } // namespace | 54 static void ensureAnimatableValueCaches( |
| 55 CSSPropertyID property, |
| 56 CSSValue& fromCSSValue, |
| 57 CSSValue& toCSSValue, |
| 58 RefPtrWillBeRawPtr<AnimatableValue>* fromAnimatableValueCache, |
| 59 RefPtrWillBeRawPtr<AnimatableValue>* toAnimatableValueCache, |
| 60 Element* element) |
| 61 { |
| 62 if (!*fromAnimatableValueCache) |
| 63 *fromAnimatableValueCache = StyleResolver::createAnimatableValueSnapshot
(*element, property, fromCSSValue); |
108 | 64 |
109 // FIXME: Refactor this into a generic piece that lives in InterpolationEffect,
and a template parameter specific converter. | 65 RefPtrWillBeRawPtr<AnimatableValue> to = StyleResolver::createAnimatableValu
eSnapshot(*element, property, toCSSValue); |
110 PassRefPtrWillBeRawPtr<Interpolation> StringKeyframe::PropertySpecificKeyframe::
maybeCreateInterpolation(CSSPropertyID property, Keyframe::PropertySpecificKeyfr
ame& end, Element* element) const | 66 *toAnimatableValueCache = to; |
| 67 } |
| 68 |
| 69 // FIXME: Remove the use of AnimatableValues and Elements here. |
| 70 PassRefPtrWillBeRawPtr<Interpolation> InterpolationFactory::maybeCreateInterpola
tion( |
| 71 CSSPropertyID property, |
| 72 CSSValue* fromCSSValue, |
| 73 CSSValue* toCSSValue, |
| 74 AnimationEffect::CompositeOperation fromComposite, |
| 75 AnimationEffect::CompositeOperation toComposite, |
| 76 RefPtrWillBeRawPtr<AnimatableValue>* fromAnimatableValueCache, |
| 77 RefPtrWillBeRawPtr<AnimatableValue>* toAnimatableValueCache, |
| 78 Element* element) |
111 { | 79 { |
112 CSSValue* fromCSSValue = m_value.get(); | 80 ASSERT(fromCSSValue); |
113 CSSValue* toCSSValue = toStringPropertySpecificKeyframe(end).value(); | 81 ASSERT(toCSSValue); |
| 82 |
114 InterpolationRange range = RangeAll; | 83 InterpolationRange range = RangeAll; |
115 bool fallBackToLegacy = false; | 84 bool fallBackToLegacy = false; |
116 | 85 |
117 // FIXME: Remove this flag once we can rely on legacy's behaviour being corr
ect. | 86 // FIXME: Remove this flag once we can rely on legacy's behaviour being corr
ect. |
118 bool forceDefaultInterpolation = false; | 87 bool forceDefaultInterpolation = false; |
119 | 88 |
120 if (!CSSPropertyMetadata::isAnimatableProperty(property)) { | 89 if (!CSSPropertyMetadata::isAnimatableProperty(property)) { |
121 if (fromCSSValue == toCSSValue) | 90 if (fromCSSValue == toCSSValue) |
122 return ConstantStyleInterpolation::create(fromCSSValue, property); | 91 return ConstantStyleInterpolation::create(fromCSSValue, property, fr
omComposite, toComposite); |
123 | 92 |
124 return nullptr; | 93 return nullptr; |
125 } | 94 } |
126 | 95 |
127 // FIXME: Generate this giant switch statement. | 96 // FIXME: Generate this giant switch statement. |
128 switch (property) { | 97 switch (property) { |
129 case CSSPropertyLineHeight: | 98 case CSSPropertyLineHeight: |
130 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) | 99 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) |
131 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, RangeNonNegative); | 100 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, RangeNonNegative); |
132 | 101 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 case CSSPropertyMarginLeft: | 136 case CSSPropertyMarginLeft: |
168 case CSSPropertyMarginRight: | 137 case CSSPropertyMarginRight: |
169 case CSSPropertyMarginTop: | 138 case CSSPropertyMarginTop: |
170 case CSSPropertyOutlineOffset: | 139 case CSSPropertyOutlineOffset: |
171 case CSSPropertyRight: | 140 case CSSPropertyRight: |
172 case CSSPropertyTop: | 141 case CSSPropertyTop: |
173 case CSSPropertyVerticalAlign: | 142 case CSSPropertyVerticalAlign: |
174 case CSSPropertyWordSpacing: | 143 case CSSPropertyWordSpacing: |
175 case CSSPropertyWebkitColumnRuleWidth: | 144 case CSSPropertyWebkitColumnRuleWidth: |
176 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) | 145 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) |
177 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, range); | 146 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, range, fromComposite, toComposite); |
178 | 147 |
179 // FIXME: Handle keywords e.g. 'none'. | 148 // FIXME: Handle keywords e.g. 'none'. |
180 if (property == CSSPropertyPerspective) | 149 if (property == CSSPropertyPerspective) |
181 fallBackToLegacy = true; | 150 fallBackToLegacy = true; |
182 // FIXME: Handle keywords e.g. 'smaller', 'larger'. | 151 // FIXME: Handle keywords e.g. 'smaller', 'larger'. |
183 if (property == CSSPropertyFontSize) | 152 if (property == CSSPropertyFontSize) |
184 fallBackToLegacy = true; | 153 fallBackToLegacy = true; |
185 | 154 |
186 // FIXME: Handle keywords e.g. 'normal' | 155 // FIXME: Handle keywords e.g. 'normal' |
187 if (property == CSSPropertyLetterSpacing) | 156 if (property == CSSPropertyLetterSpacing) |
188 fallBackToLegacy = true; | 157 fallBackToLegacy = true; |
189 | 158 |
190 // FIXME: Handle keywords e.g. 'thick' | 159 // FIXME: Handle keywords e.g. 'thick' |
191 if (property == CSSPropertyOutlineWidth || CSSPropertyWebkitColumnRuleWi
dth) | 160 if (property == CSSPropertyOutlineWidth || CSSPropertyWebkitColumnRuleWi
dth) |
192 fallBackToLegacy = true; | 161 fallBackToLegacy = true; |
193 break; | 162 break; |
194 case CSSPropertyOrphans: | 163 case CSSPropertyOrphans: |
195 case CSSPropertyWidows: | 164 case CSSPropertyWidows: |
196 case CSSPropertyZIndex: | 165 case CSSPropertyZIndex: |
197 case CSSPropertyWebkitColumnCount: | 166 case CSSPropertyWebkitColumnCount: |
198 case CSSPropertyShapeImageThreshold: | 167 case CSSPropertyShapeImageThreshold: |
199 case CSSPropertyFillOpacity: | 168 case CSSPropertyFillOpacity: |
200 case CSSPropertyFloodOpacity: | 169 case CSSPropertyFloodOpacity: |
201 case CSSPropertyOpacity: | 170 case CSSPropertyOpacity: |
202 case CSSPropertyStopOpacity: | 171 case CSSPropertyStopOpacity: |
203 case CSSPropertyStrokeOpacity: | 172 case CSSPropertyStrokeOpacity: |
204 case CSSPropertyStrokeMiterlimit: | 173 case CSSPropertyStrokeMiterlimit: |
205 case CSSPropertyZoom: | 174 case CSSPropertyZoom: |
206 if (DoubleStyleInterpolation::canCreateFrom(*fromCSSValue) && DoubleStyl
eInterpolation::canCreateFrom(*toCSSValue)) { | 175 if (DoubleStyleInterpolation::canCreateFrom(*fromCSSValue) && DoubleStyl
eInterpolation::canCreateFrom(*toCSSValue)) { |
207 if (property == CSSPropertyOpacity) | 176 if (property == CSSPropertyOpacity) { |
208 StringKeyframe::PropertySpecificKeyframe::ensureAnimatableValueC
aches(property, end, element, *fromCSSValue, *toCSSValue); | 177 // FIXME: Remove the use of AnimatableValues and Elements here. |
| 178 ASSERT(element); |
| 179 ASSERT(fromAnimatableValueCache); |
| 180 ASSERT(toAnimatableValueCache); |
| 181 |
| 182 ensureAnimatableValueCaches(property, *fromCSSValue, *toCSSValue
, fromAnimatableValueCache, toAnimatableValueCache, element); |
| 183 } |
209 return DoubleStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, toCSSPrimitiveValue(fromCSSValue)->primitiveType(), setRange(property)
); | 184 return DoubleStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, toCSSPrimitiveValue(fromCSSValue)->primitiveType(), setRange(property)
); |
210 } | 185 } |
211 break; | 186 break; |
212 | 187 |
213 case CSSPropertyMotionRotation: { | 188 case CSSPropertyMotionRotation: { |
214 RefPtrWillBeRawPtr<Interpolation> interpolation = DoubleStyleInterpolati
on::maybeCreateFromMotionRotation(*fromCSSValue, *toCSSValue, property); | 189 RefPtrWillBeRawPtr<Interpolation> interpolation = DoubleStyleInterpolati
on::maybeCreateFromMotionRotation(*fromCSSValue, *toCSSValue, property); |
215 if (interpolation) | 190 if (interpolation) |
216 return interpolation.release(); | 191 return interpolation.release(); |
217 break; | 192 break; |
218 } | 193 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 break; | 291 break; |
317 } | 292 } |
318 | 293 |
319 default: | 294 default: |
320 // Fall back to LegacyStyleInterpolation. | 295 // Fall back to LegacyStyleInterpolation. |
321 fallBackToLegacy = true; | 296 fallBackToLegacy = true; |
322 break; | 297 break; |
323 } | 298 } |
324 | 299 |
325 if (fromCSSValue == toCSSValue) | 300 if (fromCSSValue == toCSSValue) |
326 return ConstantStyleInterpolation::create(fromCSSValue, property); | 301 return ConstantStyleInterpolation::create(fromCSSValue, property, fromCo
mposite, toComposite); |
327 | 302 |
328 if (forceDefaultInterpolation) | 303 if (forceDefaultInterpolation) |
329 return nullptr; | 304 return nullptr; |
330 | 305 |
331 if (fromCSSValue->isUnsetValue() || fromCSSValue->isInheritedValue() || from
CSSValue->isInitialValue() | 306 if (fromCSSValue->isUnsetValue() || fromCSSValue->isInheritedValue() || from
CSSValue->isInitialValue() |
332 || toCSSValue->isUnsetValue() || toCSSValue->isInheritedValue() || toCSS
Value->isInitialValue()) | 307 || toCSSValue->isUnsetValue() || toCSSValue->isInheritedValue() || toCSS
Value->isInitialValue()) |
333 fallBackToLegacy = true; | 308 fallBackToLegacy = true; |
334 | 309 |
| 310 ASSERT(element); |
335 if (fallBackToLegacy) { | 311 if (fallBackToLegacy) { |
| 312 ASSERT(fromAnimatableValueCache); |
| 313 ASSERT(toAnimatableValueCache); |
| 314 |
336 if (DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(
*fromCSSValue) || DeferredLegacyStyleInterpolation::interpolationRequiresStyleRe
solve(*toCSSValue)) { | 315 if (DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(
*fromCSSValue) || DeferredLegacyStyleInterpolation::interpolationRequiresStyleRe
solve(*toCSSValue)) { |
337 // FIXME: Handle these cases outside of DeferredLegacyStyleInterpola
tion. | 316 // FIXME: Handle these cases outside of DeferredLegacyStyleInterpola
tion. |
338 return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSV
alue, property); | 317 return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSV
alue, property); |
339 } | 318 } |
340 | 319 |
341 // FIXME: Remove the use of AnimatableValues, RenderStyles and Elements
here. | 320 // FIXME: Remove the use of AnimatableValues and Elements here. |
342 // FIXME: Remove this cache | 321 ensureAnimatableValueCaches(property, *fromCSSValue, *toCSSValue, fromAn
imatableValueCache, toAnimatableValueCache, element); |
343 ASSERT(element); | |
344 if (!m_animatableValueCache) | |
345 m_animatableValueCache = StyleResolver::createAnimatableValueSnapsho
t(*element, property, *fromCSSValue); | |
346 | 322 |
347 RefPtrWillBeRawPtr<AnimatableValue> to = StyleResolver::createAnimatable
ValueSnapshot(*element, property, *toCSSValue); | 323 return LegacyStyleInterpolation::create((*fromAnimatableValueCache).get(
), (*toAnimatableValueCache).get(), property); |
348 toStringPropertySpecificKeyframe(end).m_animatableValueCache = to; | |
349 | |
350 return LegacyStyleInterpolation::create(m_animatableValueCache.get(), to
.release(), property); | |
351 } | 324 } |
352 | 325 |
353 ASSERT(AnimatableValue::usesDefaultInterpolation( | 326 ASSERT(AnimatableValue::usesDefaultInterpolation( |
354 StyleResolver::createAnimatableValueSnapshot(*element, property, *fromCS
SValue).get(), | 327 StyleResolver::createAnimatableValueSnapshot(*element, property, *fromCS
SValue).get(), |
355 StyleResolver::createAnimatableValueSnapshot(*element, property, *toCSSV
alue).get())); | 328 StyleResolver::createAnimatableValueSnapshot(*element, property, *toCSSV
alue).get())); |
356 | 329 |
357 return nullptr; | 330 return nullptr; |
358 | |
359 } | |
360 // FIXME: Remove the use of AnimatableValues, RenderStyles and Elements here. | |
361 // FIXME: Remove this cache | |
362 void StringKeyframe::PropertySpecificKeyframe::ensureAnimatableValueCaches(CSSPr
opertyID property, Keyframe::PropertySpecificKeyframe& end, Element* element, CS
SValue& fromCSSValue, CSSValue& toCSSValue) const | |
363 { | |
364 ASSERT(element); | |
365 if (!m_animatableValueCache) | |
366 m_animatableValueCache = StyleResolver::createAnimatableValueSnapshot(*e
lement, property, fromCSSValue); | |
367 RefPtrWillBeRawPtr<AnimatableValue> to = StyleResolver::createAnimatableValu
eSnapshot(*element, property, toCSSValue); | |
368 toStringPropertySpecificKeyframe(end).m_animatableValueCache = to; | |
369 } | 331 } |
370 | 332 |
371 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::Prope
rtySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> e
asing) const | 333 PassRefPtrWillBeRawPtr<Interpolation> InterpolationFactory::createConstantInterp
olation( |
| 334 CSSPropertyID property, |
| 335 CSSValue* value, |
| 336 AnimationEffect::CompositeOperation fromComposite, |
| 337 AnimationEffect::CompositeOperation toComposite) |
372 { | 338 { |
373 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, easing, 0, An
imationEffect::CompositeAdd)); | 339 RefPtrWillBeRawPtr<Interpolation> interpolation = InterpolationFactory::mayb
eCreateInterpolation( |
374 } | 340 property, |
| 341 value, |
| 342 value, |
| 343 fromComposite, |
| 344 toComposite); |
375 | 345 |
376 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::Prope
rtySpecificKeyframe::cloneWithOffset(double offset) const | 346 ASSERT(interpolation); |
377 { | |
378 Keyframe::PropertySpecificKeyframe* theClone = new PropertySpecificKeyframe(
offset, m_easing, m_value.get()); | |
379 toStringPropertySpecificKeyframe(theClone)->m_animatableValueCache = m_anima
tableValueCache; | |
380 return adoptPtrWillBeNoop(theClone); | |
381 } | |
382 | 347 |
383 void StringKeyframe::PropertySpecificKeyframe::trace(Visitor* visitor) | 348 return interpolation.release(); |
384 { | |
385 visitor->trace(m_value); | |
386 visitor->trace(m_animatableValueCache); | |
387 Keyframe::PropertySpecificKeyframe::trace(visitor); | |
388 } | 349 } |
389 | 350 |
390 } | 351 } |
OLD | NEW |