Chromium Code Reviews| Index: Source/core/animation/FilterStyleInterpolation.cpp |
| diff --git a/Source/core/animation/FilterStyleInterpolation.cpp b/Source/core/animation/FilterStyleInterpolation.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0bbb38c9b04c67d4671566134956ce029c371e8a |
| --- /dev/null |
| +++ b/Source/core/animation/FilterStyleInterpolation.cpp |
| @@ -0,0 +1,171 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "config.h" |
| +#include "core/animation/FilterStyleInterpolation.h" |
| + |
| +#include "core/animation/LengthStyleInterpolation.h" |
| +#include "core/animation/ListStyleInterpolation.h" |
| +#include "core/css/CSSPrimitiveValue.h" |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +PassRefPtr<CSSValueList> extendFilterList(const CSSValue& shortFilterValue, const CSSValue& otherFilterValue) |
| +{ |
| + const CSSValueList& shortFilterList = toCSSValueList(shortFilterValue); |
| + const CSSValueList& otherFilterList = toCSSValueList(otherFilterValue); |
| + |
| + RefPtrWillBeRawPtr<CSSValueList> result = CSSValueList::createSpaceSeparated(); |
| + CSSValueList::const_iterator shortIter = shortFilterList.begin(); |
| + CSSValueList::const_iterator otherIter = otherFilterList.begin(); |
| + while (shortIter != shortFilterList.end()) { |
| + result->append(*shortIter); |
| + ++shortIter; |
| + ++otherIter; |
| + } |
| + while (otherIter != otherFilterList.end()) { |
| + if (!(*otherIter)->isFunctionValue()) { |
| + ASSERT_NOT_REACHED(); |
|
Timothy Loh
2015/04/08 07:59:43
Do we need to have this defensive check if it'll n
Eric Willigers
2015/04/08 08:30:40
Acknowledged.
|
| + return nullptr; |
| + } |
| + |
| + CSSFunctionValue* function = toCSSFunctionValue(otherIter->get()); |
| + RefPtrWillBeRawPtr<CSSValueList> defaultFunction = CSSFunctionValue::create(function->functionType()); |
| + switch (function->functionType()) { |
| + case CSSValueUrl: |
| + // Discrete interpolation occurs - see canCreateFrom. |
| + break; |
| + case CSSValueGrayscale: |
| + case CSSValueInvert: |
| + case CSSValueSepia: |
| + defaultFunction->append(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER)); |
| + break; |
| + case CSSValueBrightness: |
| + case CSSValueContrast: |
| + case CSSValueOpacity: |
| + case CSSValueSaturate: |
| + defaultFunction->append(CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_NUMBER)); |
| + break; |
| + case CSSValueHueRotate: |
| + defaultFunction->append(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_DEG)); |
| + break; |
| + case CSSValueBlur: |
| + defaultFunction->append(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX)); |
| + break; |
| + case CSSValueDropShadow: |
| + // FIXME: Drop shadow interpolation has not been implemented. |
| + default: |
| + return nullptr; |
| + } |
| + result->append(defaultFunction); |
| + ++otherIter; |
| + } |
| + return result.release(); |
| +} |
| + |
| +} // namespace |
| + |
| +PassRefPtrWillBeRawPtr<StyleInterpolation> FilterStyleInterpolation::maybeCreate(const CSSValue& start, const CSSValue& end, CSSPropertyID property) |
| +{ |
| + size_t startLength = start.isValueList() ? toCSSValueList(start).length() : 0; |
| + size_t endLength = end.isValueList() ? toCSSValueList(end).length() : 0; |
| + if (startLength == 0 && endLength == 0) |
| + return nullptr; |
| + |
| + RefPtrWillBeRawPtr<CSSValueList> normalizedStart; |
| + RefPtrWillBeRawPtr<CSSValueList> normalizedEnd; |
| + if (startLength < endLength) { |
| + if (start.isValueList()) |
| + normalizedStart = extendFilterList(start, end); |
| + else if (start.isPrimitiveValue() && toCSSPrimitiveValue(start).getValueID() == CSSValueNone) |
| + normalizedStart = extendFilterList(*CSSValueList::createSpaceSeparated(), end); |
| + else |
| + return nullptr; |
|
Timothy Loh
2015/04/08 07:59:43
Not sure about the interpolation coding style but
Eric Willigers
2015/04/08 08:30:40
I'm allowing for 'inherit' and 'initial'.
|
| + } |
| + if (endLength < startLength) { |
| + if (end.isValueList()) |
| + normalizedEnd = extendFilterList(end, start); |
| + else if (end.isPrimitiveValue() && toCSSPrimitiveValue(end).getValueID() == CSSValueNone) |
| + normalizedEnd = extendFilterList(*CSSValueList::createSpaceSeparated(), start); |
| + else |
| + return nullptr; |
|
Timothy Loh
2015/04/08 07:59:43
and this
|
| + } |
| + |
| + return ListStyleInterpolation<FilterStyleInterpolation>::maybeCreateFromList( |
| + normalizedStart ? *normalizedStart : start, |
| + normalizedEnd ? *normalizedEnd : end, |
| + property); |
| +} |
| + |
| +bool FilterStyleInterpolation::canCreateFrom(const CSSValue& start, const CSSValue& end) |
| +{ |
| + // Discrete interpolation occurs when url or distinct function types occur. |
| + // http://dev.w3.org/fxtf/filters/#animation-of-filters |
| + // FIXME: Drop shadow interpolation has not been implemented. |
| + return start.isFunctionValue() && end.isFunctionValue() |
|
Timothy Loh
2015/04/08 07:59:43
I think these are always functionvalues?
Eric Willigers
2015/04/08 08:30:40
Acknowledged.
|
| + && toCSSFunctionValue(start).functionType() == toCSSFunctionValue(end).functionType() |
| + && toCSSFunctionValue(start).functionType() != CSSValueUrl |
| + && toCSSFunctionValue(start).functionType() != CSSValueDropShadow; |
| +} |
| + |
| +PassOwnPtrWillBeRawPtr<InterpolableValue> FilterStyleInterpolation::toInterpolableValue(const CSSValue& value, CSSValueID& functionType) |
| +{ |
| + const CSSFunctionValue& filterValue = toCSSFunctionValue(value); |
| + functionType = filterValue.functionType(); |
| + size_t length = filterValue.length(); |
| + |
| + OwnPtrWillBeRawPtr<InterpolableList> result = InterpolableList::create(length); |
| + for (size_t i = 0; i < length; ++i) { |
| + switch (functionType) { |
| + case CSSValueBlur: |
| + result->set(i, LengthStyleInterpolation::toInterpolableValue(*filterValue.item(i), CSSPropertyWebkitFilter)); |
| + break; |
| + case CSSValueDropShadow: |
| + case CSSValueUrl: |
| + ASSERT_NOT_REACHED(); |
| + default: |
| + result->set(i, InterpolableNumber::create(toCSSPrimitiveValue(filterValue.item(i))->getDoubleValue())); |
| + break; |
| + } |
| + } |
| + return result.release(); |
| +} |
| + |
| +PassRefPtrWillBeRawPtr<CSSFunctionValue> FilterStyleInterpolation::fromInterpolableValue(const InterpolableValue& value, CSSValueID functionType, InterpolationRange) |
| +{ |
| + const InterpolableList& list = toInterpolableList(value); |
| + size_t length = list.length(); |
| + RefPtrWillBeRawPtr<CSSFunctionValue> result = CSSFunctionValue::create(functionType); |
| + for (size_t i = 0; i < length; ++i) { |
| + switch (functionType) { |
| + case CSSValueGrayscale: |
| + case CSSValueInvert: |
| + case CSSValueOpacity: |
| + case CSSValueSepia: |
| + result->append(CSSPrimitiveValue::create(clampTo<double>(toInterpolableNumber(list.get(i))->value(), 0, 1), CSSPrimitiveValue::CSS_NUMBER)); |
| + break; |
| + case CSSValueBrightness: |
| + case CSSValueContrast: |
| + case CSSValueSaturate: |
| + result->append(CSSPrimitiveValue::create(clampTo<double>(toInterpolableNumber(list.get(i))->value(), 0), CSSPrimitiveValue::CSS_NUMBER)); |
| + break; |
| + case CSSValueHueRotate: |
| + result->append(CSSPrimitiveValue::create(toInterpolableNumber(list.get(i))->value(), CSSPrimitiveValue::CSS_DEG)); |
| + break; |
| + case CSSValueBlur: |
| + result->append(LengthStyleInterpolation::fromInterpolableValue(*list.get(i), RangeNonNegative)); |
| + break; |
| + case CSSValueDropShadow: |
| + case CSSValueUrl: |
| + default: |
| + ASSERT_NOT_REACHED(); |
| + break; |
| + } |
| + } |
| + return result.release(); |
| +} |
| + |
| +} // namespace blink |