PassRefPtr<Interpolation> StringKeyframe::CSSPropertySpecificKeyframe::maybeCreateInterpolation(PropertyHandle propertyHandle, Keyframe::PropertySpecificKeyframe& end, Element* element, const ComputedStyle* baseStyle) const { const InterpolationTypes* applicableTypes = applicableTypesForProperty(propertyHandle); if (applicableTypes) return InvalidatableInterpolation::create(propertyHandle, *applicableTypes, *this, end); // TODO(alancutter): Remove the remainder of this function. // FIXME: Refactor this into a generic piece that lives in InterpolationEffect, and a template parameter specific converter. CSSPropertyID property = propertyHandle.isCSSProperty() ? propertyHandle.cssProperty() : propertyHandle.presentationAttribute(); CSSValue* fromCSSValue = m_value.get(); CSSValue* toCSSValue = toCSSPropertySpecificKeyframe(end).value(); InterpolationRange range = RangeAll; // FIXME: Remove this flag once we can rely on legacy's behaviour being correct. bool forceDefaultInterpolation = false; // FIXME: Remove this check once neutral keyframes are implemented in StringKeyframes. if (!fromCSSValue || !toCSSValue) return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSValue, property); ASSERT(fromCSSValue && toCSSValue); if (!CSSPropertyMetadata::isInterpolableProperty(property)) { if (fromCSSValue == toCSSValue) return ConstantStyleInterpolation::create(fromCSSValue, property); return nullptr; } if (fromCSSValue->isCSSWideKeyword() || toCSSValue->isCSSWideKeyword()) return createLegacyStyleInterpolation(property, end, element, baseStyle); switch (property) { case CSSPropertyFontSize: if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyleInterpolation::canCreateFrom(*toCSSValue)) return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue, property, RangeNonNegative); // FIXME: Handle keywords e.g. 'smaller', 'larger'. if (property == CSSPropertyFontSize) return createLegacyStyleInterpolation(property, end, element, baseStyle); // FIXME: Handle keywords e.g. 'baseline', 'sub'. if (property == CSSPropertyBaselineShift) return createLegacyStyleInterpolation(property, end, element, baseStyle); break; case CSSPropertyMotionRotation: { RefPtr<Interpolation> interpolation = DoubleStyleInterpolation::maybeCreateFromMotionRotation(*fromCSSValue, *toCSSValue, property); if (interpolation) return interpolation.release(); break; } case CSSPropertyVisibility: if (VisibilityStyleInterpolation::canCreateFrom(*fromCSSValue) && VisibilityStyleInterpolation::canCreateFrom(*toCSSValue) && (VisibilityStyleInterpolation::isVisible(*fromCSSValue) || VisibilityStyleInterpolation::isVisible(*toCSSValue))) return VisibilityStyleInterpolation::create(*fromCSSValue, *toCSSValue, property); break; case CSSPropertyBorderBottomLeftRadius: case CSSPropertyBorderBottomRightRadius: case CSSPropertyBorderTopLeftRadius: case CSSPropertyBorderTopRightRadius: if (LengthPairStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthPairStyleInterpolation::canCreateFrom(*toCSSValue)) return LengthPairStyleInterpolation::create(*fromCSSValue, *toCSSValue, property, RangeNonNegative); break; case CSSPropertyPerspectiveOrigin: case CSSPropertyTransformOrigin: { RefPtr<Interpolation> interpolation = ListStyleInterpolation<LengthStyleInterpolation>::maybeCreateFromList(*fromCSSValue, *toCSSValue, property, range); if (interpolation) return interpolation.release(); // FIXME: Handle keywords: top, right, left, center, bottom return createLegacyStyleInterpolation(property, end, element, baseStyle); } case CSSPropertyClip: { if (LengthBoxStyleInterpolation::usesDefaultInterpolation(*fromCSSValue, *toCSSValue)) { forceDefaultInterpolation = true; break; } RefPtr<Interpolation> interpolation = LengthBoxStyleInterpolation::maybeCreateFrom(*fromCSSValue, *toCSSValue, property); if (interpolation) return interpolation.release(); break; } case CSSPropertyBorderImageSlice: case CSSPropertyWebkitMaskBoxImageSlice: { RefPtr<Interpolation> interpolation = ImageSliceStyleInterpolation::maybeCreate(*fromCSSValue, *toCSSValue, property); if (interpolation) return interpolation.release(); if (ImageSliceStyleInterpolation::usesDefaultInterpolation(*fromCSSValue, *toCSSValue)) forceDefaultInterpolation = true; break; } case CSSPropertyWebkitFilter: case CSSPropertyBackdropFilter: { RefPtr<Interpolation> interpolation = FilterStyleInterpolation::maybeCreateList(*fromCSSValue, *toCSSValue, property); if (interpolation) return interpolation.release(); // FIXME: Support drop shadow interpolation. return createLegacyStyleInterpolation(property, end, element, baseStyle); break; } case CSSPropertyTranslate: { RefPtr<Interpolation> interpolation = ListStyleInterpolation<LengthStyleInterpolation>::maybeCreateFromList(*fromCSSValue, *toCSSValue, property, range); if (interpolation) return interpolation.release(); // TODO(soonm): Legacy mode is used when from and to cssvaluelist length does not match. return createLegacyStyleInterpolation(property, end, element, baseStyle); break; } case CSSPropertyScale: { RefPtr<Interpolation> interpolation = ListStyleInterpolation<DoubleStyleInterpolation>::maybeCreateFromList(*fromCSSValue, *toCSSValue, property, range); if (interpolation) return interpolation.release(); // TODO(soonm): Legacy mode is used when from and to cssvaluelist length does not match. return createLegacyStyleInterpolation(property, end, element, baseStyle); break; } default: // Fall back to LegacyStyleInterpolation. return createLegacyStyleInterpolation(property, end, element, baseStyle); break; } if (fromCSSValue == toCSSValue) return ConstantStyleInterpolation::create(fromCSSValue, property); if (!forceDefaultInterpolation) { ASSERT(AnimatableValue::usesDefaultInterpolation( StyleResolver::createAnimatableValueSnapshot(*element, baseStyle, property, fromCSSValue).get(), StyleResolver::createAnimatableValueSnapshot(*element, baseStyle, property, toCSSValue).get())); } return nullptr; }
PassOwnPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::createPropertySpecificKeyframe(PropertyHandle property) const { if (property.isCSSProperty()) return adoptPtr(new CSSPropertySpecificKeyframe(offset(), &easing(), cssPropertyValue(property.cssProperty()), composite())); if (property.isPresentationAttribute()) return adoptPtr(new CSSPropertySpecificKeyframe(offset(), &easing(), presentationAttributeValue(property.presentationAttribute()), composite())); ASSERT(property.isSVGAttribute()); return adoptPtr(new SVGPropertySpecificKeyframe(offset(), &easing(), svgPropertyValue(property.svgAttribute()), composite())); }