| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/StringKeyframe.h" |
| 7 | 7 |
| 8 #include "core/animation/ColorStyleInterpolation.h" | 8 #include "core/animation/InterpolationFactory.h" |
| 9 #include "core/animation/ConstantStyleInterpolation.h" | 9 #include "core/animation/StyleInterpolation.h" |
| 10 #include "core/animation/DeferredLegacyStyleInterpolation.h" | |
| 11 #include "core/animation/DoubleStyleInterpolation.h" | |
| 12 #include "core/animation/ImageStyleInterpolation.h" | |
| 13 #include "core/animation/LegacyStyleInterpolation.h" | |
| 14 #include "core/animation/LengthBoxStyleInterpolation.h" | |
| 15 #include "core/animation/LengthPairStyleInterpolation.h" | |
| 16 #include "core/animation/LengthStyleInterpolation.h" | |
| 17 #include "core/animation/ListStyleInterpolation.h" | |
| 18 #include "core/animation/SVGLengthStyleInterpolation.h" | |
| 19 #include "core/animation/ShadowStyleInterpolation.h" | |
| 20 #include "core/animation/VisibilityStyleInterpolation.h" | |
| 21 #include "core/animation/css/CSSAnimations.h" | 10 #include "core/animation/css/CSSAnimations.h" |
| 22 #include "core/css/CSSPropertyMetadata.h" | 11 #include "core/css/CSSPropertyMetadata.h" |
| 23 #include "core/css/resolver/StyleResolver.h" | 12 #include "core/css/resolver/StyleResolver.h" |
| 24 #include "core/layout/style/LayoutStyle.h" | 13 #include "core/layout/style/LayoutStyle.h" |
| 25 | 14 |
| 26 namespace blink { | 15 namespace blink { |
| 27 | 16 |
| 28 StringKeyframe::StringKeyframe(const StringKeyframe& copyFrom) | 17 StringKeyframe::StringKeyframe(const StringKeyframe& copyFrom) |
| 29 : Keyframe(copyFrom.m_offset, copyFrom.m_composite, copyFrom.m_easing) | 18 : Keyframe(copyFrom.m_offset, copyFrom.m_composite, copyFrom.m_easing) |
| 30 , m_propertySet(copyFrom.m_propertySet->mutableCopy()) | 19 , m_propertySet(copyFrom.m_propertySet->mutableCopy()) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 , m_value(value) | 57 , m_value(value) |
| 69 { } | 58 { } |
| 70 | 59 |
| 71 StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset
, PassRefPtr<TimingFunction> easing, CSSValue* value) | 60 StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset
, PassRefPtr<TimingFunction> easing, CSSValue* value) |
| 72 : Keyframe::PropertySpecificKeyframe(offset, easing, AnimationEffect::Compos
iteReplace) | 61 : Keyframe::PropertySpecificKeyframe(offset, easing, AnimationEffect::Compos
iteReplace) |
| 73 , m_value(value) | 62 , m_value(value) |
| 74 { | 63 { |
| 75 ASSERT(!isNull(m_offset)); | 64 ASSERT(!isNull(m_offset)); |
| 76 } | 65 } |
| 77 | 66 |
| 78 namespace { | |
| 79 InterpolationRange setRange(CSSPropertyID id) | |
| 80 { | |
| 81 switch (id) { | |
| 82 case CSSPropertyOrphans: | |
| 83 case CSSPropertyWebkitColumnCount: | |
| 84 case CSSPropertyWidows: | |
| 85 return RangeRoundGreaterThanOrEqualToOne; | |
| 86 case CSSPropertyWebkitColumnRuleWidth: | |
| 87 case CSSPropertyZIndex: | |
| 88 return RangeRound; | |
| 89 case CSSPropertyFloodOpacity: | |
| 90 case CSSPropertyStopOpacity: | |
| 91 case CSSPropertyStrokeOpacity: | |
| 92 case CSSPropertyShapeImageThreshold: | |
| 93 return RangeZeroToOne; | |
| 94 case CSSPropertyFillOpacity: | |
| 95 case CSSPropertyOpacity: | |
| 96 return RangeOpacityFIXME; | |
| 97 case CSSPropertyStrokeMiterlimit: | |
| 98 return RangeGreaterThanOrEqualToOne; | |
| 99 case CSSPropertyZoom: | |
| 100 return RangePositive; | |
| 101 default: | |
| 102 ASSERT_NOT_REACHED(); | |
| 103 return RangeAll; | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 } // namespace | |
| 108 | |
| 109 // FIXME: Refactor this into a generic piece that lives in InterpolationEffect,
and a template parameter specific converter. | 67 // FIXME: Refactor this into a generic piece that lives in InterpolationEffect,
and a template parameter specific converter. |
| 110 PassRefPtrWillBeRawPtr<Interpolation> StringKeyframe::PropertySpecificKeyframe::
maybeCreateInterpolation(CSSPropertyID property, Keyframe::PropertySpecificKeyfr
ame& end, Element* element) const | 68 PassRefPtrWillBeRawPtr<Interpolation> StringKeyframe::PropertySpecificKeyframe::
maybeCreateInterpolation(CSSPropertyID property, Keyframe::PropertySpecificKeyfr
ame& end, Element* element) const |
| 111 { | 69 { |
| 112 CSSValue* fromCSSValue = m_value.get(); | 70 CSSValue* fromCSSValue = m_value.get(); |
| 113 CSSValue* toCSSValue = toStringPropertySpecificKeyframe(end).value(); | 71 CSSValue* toCSSValue = toStringPropertySpecificKeyframe(end).value(); |
| 114 InterpolationRange range = RangeAll; | |
| 115 bool fallBackToLegacy = false; | |
| 116 | 72 |
| 117 // FIXME: Remove this flag once we can rely on legacy's behaviour being corr
ect. | 73 return InterpolationFactory::maybeCreateInterpolation(property, fromCSSValue
, toCSSValue, m_composite, toStringPropertySpecificKeyframe(end).m_composite, &m
_animatableValueCache, &toStringPropertySpecificKeyframe(end).m_animatableValueC
ache, element); |
| 118 bool forceDefaultInterpolation = false; | |
| 119 | |
| 120 if (!CSSPropertyMetadata::isAnimatableProperty(property)) { | |
| 121 if (fromCSSValue == toCSSValue) | |
| 122 return ConstantStyleInterpolation::create(fromCSSValue, property); | |
| 123 | |
| 124 return nullptr; | |
| 125 } | |
| 126 | |
| 127 // FIXME: Generate this giant switch statement. | |
| 128 switch (property) { | |
| 129 case CSSPropertyLineHeight: | |
| 130 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) | |
| 131 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, RangeNonNegative); | |
| 132 | |
| 133 if (DoubleStyleInterpolation::canCreateFrom(*fromCSSValue) && DoubleStyl
eInterpolation::canCreateFrom(*toCSSValue)) | |
| 134 return DoubleStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, CSSPrimitiveValue::CSS_NUMBER, RangeNonNegative); | |
| 135 | |
| 136 break; | |
| 137 case CSSPropertyBorderBottomWidth: | |
| 138 case CSSPropertyBorderLeftWidth: | |
| 139 case CSSPropertyBorderRightWidth: | |
| 140 case CSSPropertyBorderTopWidth: | |
| 141 case CSSPropertyFlexBasis: | |
| 142 case CSSPropertyFontSize: | |
| 143 case CSSPropertyHeight: | |
| 144 case CSSPropertyMaxHeight: | |
| 145 case CSSPropertyMaxWidth: | |
| 146 case CSSPropertyMinHeight: | |
| 147 case CSSPropertyMinWidth: | |
| 148 case CSSPropertyMotionPosition: | |
| 149 case CSSPropertyOutlineWidth: | |
| 150 case CSSPropertyPaddingBottom: | |
| 151 case CSSPropertyPaddingLeft: | |
| 152 case CSSPropertyPaddingRight: | |
| 153 case CSSPropertyPaddingTop: | |
| 154 case CSSPropertyPerspective: | |
| 155 case CSSPropertyShapeMargin: | |
| 156 case CSSPropertyWebkitBorderHorizontalSpacing: | |
| 157 case CSSPropertyWebkitBorderVerticalSpacing: | |
| 158 case CSSPropertyWebkitColumnGap: | |
| 159 case CSSPropertyWebkitColumnWidth: | |
| 160 case CSSPropertyWidth: | |
| 161 range = RangeNonNegative; | |
| 162 // Fall through | |
| 163 case CSSPropertyBottom: | |
| 164 case CSSPropertyLeft: | |
| 165 case CSSPropertyLetterSpacing: | |
| 166 case CSSPropertyMarginBottom: | |
| 167 case CSSPropertyMarginLeft: | |
| 168 case CSSPropertyMarginRight: | |
| 169 case CSSPropertyMarginTop: | |
| 170 case CSSPropertyOutlineOffset: | |
| 171 case CSSPropertyRight: | |
| 172 case CSSPropertyTop: | |
| 173 case CSSPropertyVerticalAlign: | |
| 174 case CSSPropertyWordSpacing: | |
| 175 case CSSPropertyWebkitColumnRuleWidth: | |
| 176 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) | |
| 177 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, range); | |
| 178 | |
| 179 // FIXME: Handle keywords e.g. 'none'. | |
| 180 if (property == CSSPropertyPerspective) | |
| 181 fallBackToLegacy = true; | |
| 182 // FIXME: Handle keywords e.g. 'smaller', 'larger'. | |
| 183 if (property == CSSPropertyFontSize) | |
| 184 fallBackToLegacy = true; | |
| 185 | |
| 186 // FIXME: Handle keywords e.g. 'normal' | |
| 187 if (property == CSSPropertyLetterSpacing) | |
| 188 fallBackToLegacy = true; | |
| 189 | |
| 190 // FIXME: Handle keywords e.g. 'thick' | |
| 191 if (property == CSSPropertyOutlineWidth || CSSPropertyWebkitColumnRuleWi
dth) | |
| 192 fallBackToLegacy = true; | |
| 193 break; | |
| 194 case CSSPropertyOrphans: | |
| 195 case CSSPropertyWidows: | |
| 196 case CSSPropertyZIndex: | |
| 197 case CSSPropertyWebkitColumnCount: | |
| 198 case CSSPropertyShapeImageThreshold: | |
| 199 case CSSPropertyFillOpacity: | |
| 200 case CSSPropertyFloodOpacity: | |
| 201 case CSSPropertyOpacity: | |
| 202 case CSSPropertyStopOpacity: | |
| 203 case CSSPropertyStrokeOpacity: | |
| 204 case CSSPropertyStrokeMiterlimit: | |
| 205 case CSSPropertyZoom: | |
| 206 if (DoubleStyleInterpolation::canCreateFrom(*fromCSSValue) && DoubleStyl
eInterpolation::canCreateFrom(*toCSSValue)) { | |
| 207 if (property == CSSPropertyOpacity) | |
| 208 StringKeyframe::PropertySpecificKeyframe::ensureAnimatableValueC
aches(property, end, element, *fromCSSValue, *toCSSValue); | |
| 209 return DoubleStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, toCSSPrimitiveValue(fromCSSValue)->primitiveType(), setRange(property)
); | |
| 210 } | |
| 211 break; | |
| 212 | |
| 213 case CSSPropertyMotionRotation: { | |
| 214 RefPtrWillBeRawPtr<Interpolation> interpolation = DoubleStyleInterpolati
on::maybeCreateFromMotionRotation(*fromCSSValue, *toCSSValue, property); | |
| 215 if (interpolation) | |
| 216 return interpolation.release(); | |
| 217 break; | |
| 218 } | |
| 219 case CSSPropertyVisibility: | |
| 220 if (VisibilityStyleInterpolation::canCreateFrom(*fromCSSValue) && Visibi
lityStyleInterpolation::canCreateFrom(*toCSSValue) && (VisibilityStyleInterpolat
ion::isVisible(*fromCSSValue) || VisibilityStyleInterpolation::isVisible(*toCSSV
alue))) | |
| 221 return VisibilityStyleInterpolation::create(*fromCSSValue, *toCSSVal
ue, property); | |
| 222 | |
| 223 break; | |
| 224 | |
| 225 case CSSPropertyBackgroundColor: | |
| 226 case CSSPropertyBorderBottomColor: | |
| 227 case CSSPropertyBorderLeftColor: | |
| 228 case CSSPropertyBorderRightColor: | |
| 229 case CSSPropertyBorderTopColor: | |
| 230 case CSSPropertyColor: | |
| 231 case CSSPropertyFloodColor: | |
| 232 case CSSPropertyLightingColor: | |
| 233 case CSSPropertyOutlineColor: | |
| 234 case CSSPropertyStopColor: | |
| 235 case CSSPropertyTextDecorationColor: | |
| 236 case CSSPropertyWebkitColumnRuleColor: | |
| 237 case CSSPropertyWebkitTextStrokeColor: | |
| 238 { | |
| 239 RefPtrWillBeRawPtr<Interpolation> interpolation = ColorStyleInterpol
ation::maybeCreateFromColor(*fromCSSValue, *toCSSValue, property); | |
| 240 if (interpolation) | |
| 241 return interpolation.release(); | |
| 242 | |
| 243 // Current color should use LegacyStyleInterpolation | |
| 244 if (ColorStyleInterpolation::shouldUseLegacyStyleInterpolation(*from
CSSValue, *toCSSValue)) | |
| 245 fallBackToLegacy = true; | |
| 246 | |
| 247 break; | |
| 248 } | |
| 249 | |
| 250 case CSSPropertyBorderImageSource: | |
| 251 case CSSPropertyListStyleImage: | |
| 252 case CSSPropertyWebkitMaskBoxImageSource: | |
| 253 if (ImageStyleInterpolation::canCreateFrom(*fromCSSValue) && ImageStyleI
nterpolation::canCreateFrom(*toCSSValue)) | |
| 254 return ImageStyleInterpolation::create(*fromCSSValue, *toCSSValue, p
roperty); | |
| 255 | |
| 256 // FIXME: Handle gradients. | |
| 257 fallBackToLegacy = true; | |
| 258 break; | |
| 259 case CSSPropertyBorderBottomLeftRadius: | |
| 260 case CSSPropertyBorderBottomRightRadius: | |
| 261 case CSSPropertyBorderTopLeftRadius: | |
| 262 case CSSPropertyBorderTopRightRadius: | |
| 263 range = RangeNonNegative; | |
| 264 // Fall through | |
| 265 case CSSPropertyObjectPosition: | |
| 266 if (LengthPairStyleInterpolation::canCreateFrom(*fromCSSValue) && Length
PairStyleInterpolation::canCreateFrom(*toCSSValue)) | |
| 267 return LengthPairStyleInterpolation::create(*fromCSSValue, *toCSSVal
ue, property, range); | |
| 268 break; | |
| 269 | |
| 270 case CSSPropertyPerspectiveOrigin: | |
| 271 case CSSPropertyTransformOrigin: { | |
| 272 RefPtrWillBeRawPtr<Interpolation> interpolation = ListStyleInterpolation
<LengthStyleInterpolation>::maybeCreateFromList(*fromCSSValue, *toCSSValue, prop
erty, range); | |
| 273 if (interpolation) | |
| 274 return interpolation.release(); | |
| 275 break; | |
| 276 } | |
| 277 | |
| 278 case CSSPropertyBoxShadow: | |
| 279 case CSSPropertyTextShadow: | |
| 280 case CSSPropertyWebkitBoxShadow: { | |
| 281 RefPtrWillBeRawPtr<Interpolation> interpolation = ListStyleInterpolation
<ShadowStyleInterpolation>::maybeCreateFromList(*fromCSSValue, *toCSSValue, prop
erty); | |
| 282 if (interpolation) | |
| 283 return interpolation.release(); | |
| 284 | |
| 285 // FIXME: AnimatableShadow incorrectly animates between inset and non-in
set values so it will never indicate it needs default interpolation | |
| 286 if (ShadowStyleInterpolation::usesDefaultStyleInterpolation(*fromCSSValu
e, *toCSSValue)) { | |
| 287 forceDefaultInterpolation = true; | |
| 288 break; | |
| 289 } | |
| 290 | |
| 291 // FIXME: Handle interpolation from/to none, unspecified color values | |
| 292 fallBackToLegacy = true; | |
| 293 | |
| 294 break; | |
| 295 | |
| 296 } | |
| 297 | |
| 298 case CSSPropertyClip: | |
| 299 case CSSPropertyBorderImageSlice: | |
| 300 case CSSPropertyWebkitMaskBoxImageSlice: { | |
| 301 RefPtrWillBeRawPtr<Interpolation> interpolation = LengthBoxStyleInterpol
ation::maybeCreateFrom(fromCSSValue, toCSSValue, property); | |
| 302 if (interpolation) | |
| 303 return interpolation.release(); | |
| 304 break; | |
| 305 } | |
| 306 | |
| 307 case CSSPropertyStrokeWidth: | |
| 308 range = RangeNonNegative; | |
| 309 // Fall through | |
| 310 case CSSPropertyBaselineShift: | |
| 311 case CSSPropertyStrokeDashoffset: { | |
| 312 RefPtrWillBeRawPtr<Interpolation> interpolation = SVGLengthStyleInterpol
ation::maybeCreate(*fromCSSValue, *toCSSValue, property, range); | |
| 313 if (interpolation) | |
| 314 return interpolation.release(); | |
| 315 | |
| 316 break; | |
| 317 } | |
| 318 | |
| 319 default: | |
| 320 // Fall back to LegacyStyleInterpolation. | |
| 321 fallBackToLegacy = true; | |
| 322 break; | |
| 323 } | |
| 324 | |
| 325 if (fromCSSValue == toCSSValue) | |
| 326 return ConstantStyleInterpolation::create(fromCSSValue, property); | |
| 327 | |
| 328 if (forceDefaultInterpolation) | |
| 329 return nullptr; | |
| 330 | |
| 331 if (fromCSSValue->isUnsetValue() || fromCSSValue->isInheritedValue() || from
CSSValue->isInitialValue() | |
| 332 || toCSSValue->isUnsetValue() || toCSSValue->isInheritedValue() || toCSS
Value->isInitialValue()) | |
| 333 fallBackToLegacy = true; | |
| 334 | |
| 335 if (fallBackToLegacy) { | |
| 336 if (DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(
*fromCSSValue) || DeferredLegacyStyleInterpolation::interpolationRequiresStyleRe
solve(*toCSSValue)) { | |
| 337 // FIXME: Handle these cases outside of DeferredLegacyStyleInterpola
tion. | |
| 338 return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSV
alue, property); | |
| 339 } | |
| 340 | |
| 341 // FIXME: Remove the use of AnimatableValues, RenderStyles and Elements
here. | |
| 342 // FIXME: Remove this cache | |
| 343 ASSERT(element); | |
| 344 if (!m_animatableValueCache) | |
| 345 m_animatableValueCache = StyleResolver::createAnimatableValueSnapsho
t(*element, property, *fromCSSValue); | |
| 346 | |
| 347 RefPtrWillBeRawPtr<AnimatableValue> to = StyleResolver::createAnimatable
ValueSnapshot(*element, property, *toCSSValue); | |
| 348 toStringPropertySpecificKeyframe(end).m_animatableValueCache = to; | |
| 349 | |
| 350 return LegacyStyleInterpolation::create(m_animatableValueCache.get(), to
.release(), property); | |
| 351 } | |
| 352 | |
| 353 ASSERT(AnimatableValue::usesDefaultInterpolation( | |
| 354 StyleResolver::createAnimatableValueSnapshot(*element, property, *fromCS
SValue).get(), | |
| 355 StyleResolver::createAnimatableValueSnapshot(*element, property, *toCSSV
alue).get())); | |
| 356 | |
| 357 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 } | 74 } |
| 370 | 75 |
| 371 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::Prope
rtySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> e
asing) const | 76 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::Prope
rtySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> e
asing) const |
| 372 { | 77 { |
| 373 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, easing, 0, An
imationEffect::CompositeAdd)); | 78 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, easing, 0, An
imationEffect::CompositeAdd)); |
| 374 } | 79 } |
| 375 | 80 |
| 376 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::Prope
rtySpecificKeyframe::cloneWithOffset(double offset) const | 81 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::Prope
rtySpecificKeyframe::cloneWithOffset(double offset) const |
| 377 { | 82 { |
| 378 Keyframe::PropertySpecificKeyframe* theClone = new PropertySpecificKeyframe(
offset, m_easing, m_value.get()); | 83 Keyframe::PropertySpecificKeyframe* theClone = new PropertySpecificKeyframe(
offset, m_easing, m_value.get()); |
| 379 toStringPropertySpecificKeyframe(theClone)->m_animatableValueCache = m_anima
tableValueCache; | 84 toStringPropertySpecificKeyframe(theClone)->m_animatableValueCache = m_anima
tableValueCache; |
| 380 return adoptPtrWillBeNoop(theClone); | 85 return adoptPtrWillBeNoop(theClone); |
| 381 } | 86 } |
| 382 | 87 |
| 383 void StringKeyframe::PropertySpecificKeyframe::trace(Visitor* visitor) | 88 void StringKeyframe::PropertySpecificKeyframe::trace(Visitor* visitor) |
| 384 { | 89 { |
| 385 visitor->trace(m_value); | 90 visitor->trace(m_value); |
| 386 visitor->trace(m_animatableValueCache); | 91 visitor->trace(m_animatableValueCache); |
| 387 Keyframe::PropertySpecificKeyframe::trace(visitor); | 92 Keyframe::PropertySpecificKeyframe::trace(visitor); |
| 388 } | 93 } |
| 389 | 94 |
| 390 } | 95 } |
| OLD | NEW |