Chromium Code Reviews| Index: Source/core/animation/LengthInterpolationType.cpp |
| diff --git a/Source/core/animation/LengthInterpolationType.cpp b/Source/core/animation/LengthInterpolationType.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..398a4d836d881ae0728be7815faa755df837cde3 |
| --- /dev/null |
| +++ b/Source/core/animation/LengthInterpolationType.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/LengthInterpolationType.h" |
| + |
| +#include "core/animation/LengthPropertyFunctions.h" |
| +#include "core/animation/LengthStyleInterpolation.h" |
| +#include "core/css/resolver/StyleResolverState.h" |
| + |
| +namespace blink { |
| + |
| +LengthInterpolationType::LengthInterpolationType(CSSPropertyID property) |
| + : InterpolationType(property) |
| + , m_valueRange(LengthPropertyFunctions::valueRange(property)) |
| + , m_lengthSetter(LengthPropertyFunctions::computedStyleSetter(property)) |
| +{ } |
| + |
| +static PassOwnPtrWillBeRawPtr<InterpolableList> createNeutralValue() |
| +{ |
| + OwnPtrWillBeRawPtr<InterpolableList> listOfValuesAndTypes = InterpolableList::create(2); |
| + const size_t length = CSSPrimitiveValue::LengthUnitTypeCount; |
| + OwnPtrWillBeRawPtr<InterpolableList> listOfValues = InterpolableList::create(length); |
| + OwnPtrWillBeRawPtr<InterpolableList> listOfTypes = InterpolableList::create(length); |
| + for (size_t i = 0; i < length; i++) { |
| + listOfValues->set(i, InterpolableNumber::create(0)); |
| + listOfTypes->set(i, InterpolableNumber::create(0)); |
| + } |
| + listOfValuesAndTypes->set(0, listOfValues.release()); |
| + listOfValuesAndTypes->set(1, listOfTypes.release()); |
|
shans
2015/07/02 12:02:47
listOfTypes can now be a NIV, and pairwise convers
alancutter (OOO until 2018)
2015/07/03 01:38:22
Added TODO.
|
| + return listOfValuesAndTypes.release(); |
| +} |
| + |
| +static PassOwnPtrWillBeRawPtr<InterpolableValue> maybeConvertLength(const Length& length) |
| +{ |
| + if (!length.isSpecified()) |
| + return nullptr; |
| + |
| + PixelsAndPercent pixelsAndPercent = length.pixelsAndPercent(); |
| + OwnPtrWillBeRawPtr<InterpolableList> valuesAndTypes = createNeutralValue(); |
| + |
| + InterpolableList& values = toInterpolableList(*valuesAndTypes->get(0)); |
| + values.set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pixelsAndPercent.pixels)); |
| + values.set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(pixelsAndPercent.percent)); |
| + |
| + InterpolableList& types = toInterpolableList(*valuesAndTypes->get(1)); |
| + types.set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(1)); |
| + types.set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(1)); |
| + |
| + return valuesAndTypes.release(); |
| +} |
| + |
| +class ParentLengthChecker : public InterpolationType::ConversionChecker { |
| +public: |
| + static PassOwnPtrWillBeRawPtr<ParentLengthChecker> create(CSSPropertyID property, const Length& length) |
| + { |
| + return adoptPtrWillBeNoop(new ParentLengthChecker(property, length)); |
| + } |
| + |
| +private: |
| + ParentLengthChecker(CSSPropertyID property, const Length& length) |
| + : m_property(property) |
| + , m_length(length) |
| + { } |
| + |
| + virtual bool isValid(const StyleResolverState& state) const override final |
| + { |
| + Length parentLength; |
| + if (!LengthPropertyFunctions::getLength(m_property, *state.parentStyle(), parentLength)) |
| + return true; |
| + return parentLength == m_length; |
| + } |
| + |
| + DEFINE_INLINE_VIRTUAL_TRACE() |
| + { |
| + ConversionChecker::trace(visitor); |
| + } |
| + |
| + const CSSPropertyID m_property; |
| + const Length m_length; |
| +}; |
| + |
| +PassOwnPtrWillBeRawPtr<InterpolationValue> LengthInterpolationType::maybeConvertSingle(const CSSPropertySpecificKeyframe& keyframe, const StyleResolverState* state, ConversionCheckers& conversionCheckers) const |
| +{ |
| + if (!keyframe.value()) |
| + return InterpolationValue::create(*this, createNeutralValue()); |
| + |
| + const CSSValue& value = *keyframe.value(); |
| + |
| + if (value.isInitialValue() || (value.isUnsetValue() && !CSSPropertyMetadata::isInheritedProperty(m_property))) { |
| + Length initialLength; |
| + if (!LengthPropertyFunctions::getInitialLength(m_property, initialLength)) |
| + return nullptr; |
| + OwnPtrWillBeRawPtr<InterpolableValue> interpolableValue = maybeConvertLength(initialLength); |
| + return interpolableValue ? InterpolationValue::create(*this, interpolableValue.release()) : nullptr; |
| + } |
| + |
| + if (value.isInheritedValue() || (value.isUnsetValue() && CSSPropertyMetadata::isInheritedProperty(m_property))) { |
| + if (!state) |
| + return nullptr; |
| + Length inheritedLength; |
| + if (!LengthPropertyFunctions::getLength(m_property, *state->parentStyle(), inheritedLength)) |
| + return nullptr; |
| + conversionCheckers.append(ParentLengthChecker::create(m_property, inheritedLength)); |
| + OwnPtrWillBeRawPtr<InterpolableValue> interpolableValue = maybeConvertLength(inheritedLength); |
| + if (!interpolableValue) |
| + return nullptr; |
| + return InterpolationValue::create(*this, interpolableValue.release()); |
| + } |
| + |
| + if (!value.isPrimitiveValue()) |
| + return nullptr; |
| + |
| + const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(*keyframe.value()); |
| + |
| + OwnPtrWillBeRawPtr<InterpolableList> listOfValuesAndTypes = InterpolableList::create(2); |
| + OwnPtrWillBeRawPtr<InterpolableList> listOfValues = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount); |
| + OwnPtrWillBeRawPtr<InterpolableList> listOfTypes = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount); |
| + |
| + CSSLengthArray arrayOfValues; |
| + CSSLengthTypeArray arrayOfTypes; |
| + for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) |
| + arrayOfValues.append(0); |
| + arrayOfTypes.ensureSize(CSSPrimitiveValue::LengthUnitTypeCount); |
| + |
| + if (primitiveValue.isValueID()) { |
| + CSSValueID valueID = primitiveValue.getValueID(); |
| + double pixels; |
| + if (!LengthPropertyFunctions::getPixelsForKeyword(m_property, valueID, pixels)) |
| + return nullptr; |
| + arrayOfTypes.set(CSSPrimitiveValue::UnitTypePixels); |
| + arrayOfValues[CSSPrimitiveValue::UnitTypePixels] = pixels; |
| + } else { |
| + if (!primitiveValue.isCalculated() && !primitiveValue.isCalculatedPercentageWithLength()) { |
| + CSSPrimitiveValue::LengthUnitType type; |
| + // Only returns true if the type is a primitive length unit. |
| + if (!CSSPrimitiveValue::unitTypeToLengthUnitType(primitiveValue.primitiveType(), type)) |
| + return nullptr; |
| + } |
| + primitiveValue.accumulateLengthArray(arrayOfValues, arrayOfTypes); |
| + } |
| + |
| + for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| + listOfValues->set(i, InterpolableNumber::create(arrayOfValues.at(i))); |
| + listOfTypes->set(i, InterpolableNumber::create(arrayOfTypes.get(i))); |
| + } |
| + |
| + listOfValuesAndTypes->set(0, listOfValues.release()); |
| + listOfValuesAndTypes->set(1, listOfTypes.release()); |
| + |
| + return InterpolationValue::create(*this, listOfValuesAndTypes.release()); |
|
shans
2015/07/02 12:02:48
This is very long, and seems to need to do a bunch
dstockwell
2015/07/02 23:57:46
+1
alancutter (OOO until 2018)
2015/07/03 01:38:22
Done.
|
| +} |
| + |
| +PassOwnPtrWillBeRawPtr<InterpolationValue> LengthInterpolationType::maybeConvertUnderlyingValue(const StyleResolverState& state) const |
| +{ |
| + Length underlyingLength; |
| + if (!LengthPropertyFunctions::getLength(m_property, *state.style(), underlyingLength)) |
| + return nullptr; |
| + OwnPtrWillBeRawPtr<InterpolableValue> interpolableValue = maybeConvertLength(underlyingLength); |
| + return interpolableValue ? InterpolationValue::create(*this, interpolableValue.release()) : nullptr; |
| +} |
| + |
| +void LengthInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue*, StyleResolverState& state) const |
| +{ |
| + // TODO(alancutter): Make all length interpolation functions operate on ValueRanges instead of InterpolationRanges. |
| + InterpolationRange range = m_valueRange == ValueRangeNonNegative ? RangeNonNegative : RangeAll; |
| + LengthStyleInterpolation::applyInterpolableValue(m_property, interpolableValue, range, state, m_lengthSetter); |
| +} |
| + |
| +} // namespace blink |