Chromium Code Reviews| Index: third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp |
| diff --git a/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp |
| index e40e294ac45cb45a2d73d3c31a4086c30ef2a584..64a5aeac942a5f0a002d55eb02b7eff92089c867 100644 |
| --- a/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp |
| +++ b/third_party/WebKit/Source/core/animation/CSSLengthInterpolationType.cpp |
| @@ -4,6 +4,7 @@ |
| #include "core/animation/CSSLengthInterpolationType.h" |
| +#include "core/animation/LengthInterpolationFunctions.h" |
| #include "core/animation/LengthPropertyFunctions.h" |
| #include "core/animation/css/CSSAnimatableValueFactory.h" |
| #include "core/css/CSSCalculationValue.h" |
| @@ -14,36 +15,6 @@ |
| namespace blink { |
| -// This class is implemented as a singleton whose instance represents the presence of percentages being used in a Length value |
| -// while nullptr represents the absence of any percentages. |
| -class CSSLengthNonInterpolableValue : public NonInterpolableValue { |
| -public: |
| - ~CSSLengthNonInterpolableValue() final { NOTREACHED(); } |
| - static PassRefPtr<CSSLengthNonInterpolableValue> create(bool hasPercentage) |
| - { |
| - DEFINE_STATIC_REF(CSSLengthNonInterpolableValue, singleton, adoptRef(new CSSLengthNonInterpolableValue())); |
| - DCHECK(singleton); |
| - return hasPercentage ? singleton : nullptr; |
| - } |
| - static PassRefPtr<CSSLengthNonInterpolableValue> merge(const NonInterpolableValue* a, const NonInterpolableValue* b) |
| - { |
| - return create(hasPercentage(a) || hasPercentage(b)); |
| - } |
| - static bool hasPercentage(const NonInterpolableValue* nonInterpolableValue) |
| - { |
| - DCHECK(!nonInterpolableValue || nonInterpolableValue->getType() == CSSLengthNonInterpolableValue::staticType); |
| - return static_cast<bool>(nonInterpolableValue); |
| - } |
| - |
| - DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
| - |
| -private: |
| - CSSLengthNonInterpolableValue() { } |
| -}; |
| - |
| -DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSLengthNonInterpolableValue); |
| -DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSLengthNonInterpolableValue); |
| - |
| CSSLengthInterpolationType::CSSLengthInterpolationType(CSSPropertyID property) |
| : CSSInterpolationType(property) |
| , m_valueRange(LengthPropertyFunctions::getValueRange(property)) |
| @@ -54,98 +25,6 @@ float CSSLengthInterpolationType::effectiveZoom(const ComputedStyle& style) cons |
| return LengthPropertyFunctions::isZoomedLength(cssProperty()) ? style.effectiveZoom() : 1; |
| } |
| -std::unique_ptr<InterpolableValue> CSSLengthInterpolationType::createInterpolablePixels(double pixels) |
| -{ |
| - std::unique_ptr<InterpolableList> interpolableList = createNeutralInterpolableValue(); |
| - interpolableList->set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pixels)); |
| - return std::move(interpolableList); |
| -} |
| - |
| -InterpolationValue CSSLengthInterpolationType::createInterpolablePercent(double percent) |
| -{ |
| - std::unique_ptr<InterpolableList> interpolableList = createNeutralInterpolableValue(); |
| - interpolableList->set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(percent)); |
| - return InterpolationValue(std::move(interpolableList), CSSLengthNonInterpolableValue::create(true)); |
| -} |
| - |
| -InterpolationValue CSSLengthInterpolationType::maybeConvertLength(const Length& length, float zoom) |
| -{ |
| - if (!length.isSpecified()) |
| - return nullptr; |
| - |
| - PixelsAndPercent pixelsAndPercent = length.getPixelsAndPercent(); |
| - std::unique_ptr<InterpolableList> values = createNeutralInterpolableValue(); |
| - values->set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pixelsAndPercent.pixels / zoom)); |
| - values->set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(pixelsAndPercent.percent)); |
| - |
| - return InterpolationValue(std::move(values), CSSLengthNonInterpolableValue::create(length.hasPercent())); |
| -} |
| - |
| -std::unique_ptr<InterpolableList> CSSLengthInterpolationType::createNeutralInterpolableValue() |
| -{ |
| - const size_t length = CSSPrimitiveValue::LengthUnitTypeCount; |
| - std::unique_ptr<InterpolableList> values = InterpolableList::create(length); |
| - for (size_t i = 0; i < length; i++) |
| - values->set(i, InterpolableNumber::create(0)); |
| - return values; |
| -} |
| - |
| -PairwiseInterpolationValue CSSLengthInterpolationType::staticMergeSingleConversions(InterpolationValue&& start, InterpolationValue&& end) |
| -{ |
| - return PairwiseInterpolationValue( |
| - std::move(start.interpolableValue), |
| - std::move(end.interpolableValue), |
| - CSSLengthNonInterpolableValue::merge(start.nonInterpolableValue.get(), end.nonInterpolableValue.get())); |
| -} |
| - |
| -bool CSSLengthInterpolationType::nonInterpolableValuesAreCompatible(const NonInterpolableValue*, const NonInterpolableValue*) |
| -{ |
| - return true; |
| -} |
| - |
| -void CSSLengthInterpolationType::composite( |
| - std::unique_ptr<InterpolableValue>& underlyingInterpolableValue, |
| - RefPtr<NonInterpolableValue>& underlyingNonInterpolableValue, |
| - double underlyingFraction, |
| - const InterpolableValue& interpolableValue, |
| - const NonInterpolableValue* nonInterpolableValue) |
| -{ |
| - underlyingInterpolableValue->scaleAndAdd(underlyingFraction, interpolableValue); |
| - underlyingNonInterpolableValue = CSSLengthNonInterpolableValue::merge(underlyingNonInterpolableValue.get(), nonInterpolableValue); |
| -} |
| - |
| -void CSSLengthInterpolationType::subtractFromOneHundredPercent(InterpolationValue& result) |
| -{ |
| - InterpolableList& list = toInterpolableList(*result.interpolableValue); |
| - for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| - double value = -toInterpolableNumber(*list.get(i)).value(); |
| - if (i == CSSPrimitiveValue::UnitTypePercentage) |
| - value += 100; |
| - toInterpolableNumber(*list.getMutable(i)).set(value); |
| - } |
| - result.nonInterpolableValue = CSSLengthNonInterpolableValue::create(true); |
| -} |
| - |
| -InterpolationValue CSSLengthInterpolationType::maybeConvertCSSValue(const CSSValue& value) |
| -{ |
| - if (!value.isPrimitiveValue()) |
| - return nullptr; |
| - |
| - const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value); |
| - if (!primitiveValue.isLength() && !primitiveValue.isPercentage() && !primitiveValue.isCalculatedPercentageWithLength()) |
| - return nullptr; |
| - |
| - CSSLengthArray lengthArray; |
| - primitiveValue.accumulateLengthArray(lengthArray); |
| - |
| - std::unique_ptr<InterpolableList> values = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount); |
| - for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) |
| - values->set(i, InterpolableNumber::create(lengthArray.values[i])); |
| - |
| - bool hasPercentage = lengthArray.typeFlags.get(CSSPrimitiveValue::UnitTypePercentage); |
| - return InterpolationValue(std::move(values), CSSLengthNonInterpolableValue::create(hasPercentage)); |
| -} |
| - |
| class ParentLengthChecker : public InterpolationType::ConversionChecker { |
| public: |
| static std::unique_ptr<ParentLengthChecker> create(CSSPropertyID property, const Length& length) |
| @@ -173,7 +52,7 @@ private: |
| InterpolationValue CSSLengthInterpolationType::maybeConvertNeutral(const InterpolationValue&, ConversionCheckers&) const |
| { |
| - return InterpolationValue(createNeutralInterpolableValue()); |
| + return InterpolationValue(LengthInterpolationFunctions::createNeutralInterpolableValue()); |
| } |
| InterpolationValue CSSLengthInterpolationType::maybeConvertInitial(const StyleResolverState&, ConversionCheckers& conversionCheckers) const |
| @@ -181,7 +60,7 @@ InterpolationValue CSSLengthInterpolationType::maybeConvertInitial(const StyleRe |
| Length initialLength; |
| if (!LengthPropertyFunctions::getInitialLength(cssProperty(), initialLength)) |
| return nullptr; |
| - return maybeConvertLength(initialLength, 1); |
| + return LengthInterpolationFunctions::maybeConvertLength(initialLength, 1); |
| } |
| InterpolationValue CSSLengthInterpolationType::maybeConvertInherit(const StyleResolverState& state, ConversionCheckers& conversionCheckers) const |
| @@ -192,7 +71,7 @@ InterpolationValue CSSLengthInterpolationType::maybeConvertInherit(const StyleRe |
| if (!LengthPropertyFunctions::getLength(cssProperty(), *state.parentStyle(), inheritedLength)) |
| return nullptr; |
| conversionCheckers.append(ParentLengthChecker::create(cssProperty(), inheritedLength)); |
| - return maybeConvertLength(inheritedLength, effectiveZoom(*state.parentStyle())); |
| + return LengthInterpolationFunctions::maybeConvertLength(inheritedLength, effectiveZoom(*state.parentStyle())); |
| } |
| InterpolationValue CSSLengthInterpolationType::maybeConvertValue(const CSSValue& value, const StyleResolverState&, ConversionCheckers& conversionCheckers) const |
| @@ -202,10 +81,15 @@ InterpolationValue CSSLengthInterpolationType::maybeConvertValue(const CSSValue& |
| double pixels; |
| if (!LengthPropertyFunctions::getPixelsForKeyword(cssProperty(), valueID, pixels)) |
| return nullptr; |
| - return InterpolationValue(createInterpolablePixels(pixels)); |
| + return InterpolationValue(LengthInterpolationFunctions::createInterpolablePixels(pixels)); |
| } |
| - return maybeConvertCSSValue(value); |
| + return LengthInterpolationFunctions::maybeConvertCSSValue(value); |
| +} |
| + |
| +PairwiseInterpolationValue CSSLengthInterpolationType::maybeMergeSingles(InterpolationValue&& start, InterpolationValue&& end) const |
| +{ |
| + return LengthInterpolationFunctions::mergeSingles(std::move(start), std::move(end)); |
| } |
| InterpolationValue CSSLengthInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const |
| @@ -213,131 +97,33 @@ InterpolationValue CSSLengthInterpolationType::maybeConvertUnderlyingValue(const |
| Length underlyingLength; |
| if (!LengthPropertyFunctions::getLength(cssProperty(), *environment.state().style(), underlyingLength)) |
| return nullptr; |
| - return maybeConvertLength(underlyingLength, effectiveZoom(*environment.state().style())); |
| + return LengthInterpolationFunctions::maybeConvertLength(underlyingLength, effectiveZoom(*environment.state().style())); |
| } |
| void CSSLengthInterpolationType::composite(UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationValue& value, double interpolationFraction) const |
| { |
| InterpolationValue& underlying = underlyingValueOwner.mutableValue(); |
| - composite(underlying.interpolableValue, underlying.nonInterpolableValue, |
| + LengthInterpolationFunctions::composite(underlying.interpolableValue, underlying.nonInterpolableValue, |
| underlyingFraction, *value.interpolableValue, value.nonInterpolableValue.get()); |
| } |
| -static bool isPixelsOrPercentOnly(const InterpolableList& values) |
| -{ |
| - for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| - if (i == CSSPrimitiveValue::UnitTypePixels || i == CSSPrimitiveValue::UnitTypePercentage) |
| - continue; |
| - if (toInterpolableNumber(values.get(i))->value()) |
| - return false; |
| - } |
| - return true; |
| -} |
| - |
| -// TODO(alancutter): Move this to Length.h. |
| -static double clampToRange(double x, ValueRange range) |
| -{ |
| - return (range == ValueRangeNonNegative && x < 0) ? 0 : x; |
| -} |
| - |
| -static Length createLength(double pixels, double percentage, bool hasPercentage, ValueRange range) |
| -{ |
| - if (percentage != 0) |
| - hasPercentage = true; |
| - if (pixels != 0 && hasPercentage) |
| - return Length(CalculationValue::create(PixelsAndPercent(pixels, percentage), range)); |
| - if (hasPercentage) |
| - return Length(clampToRange(percentage, range), Percent); |
| - return Length(CSSPrimitiveValue::clampToCSSLengthRange(clampToRange(pixels, range)), Fixed); |
| -} |
| - |
| -static Length resolveInterpolablePixelsOrPercentageLength(const InterpolableList& values, bool hasPercentage, ValueRange range, double zoom) |
| -{ |
| - DCHECK(isPixelsOrPercentOnly(values)); |
| - double pixels = toInterpolableNumber(values.get(CSSPrimitiveValue::UnitTypePixels))->value() * zoom; |
| - double percentage = toInterpolableNumber(values.get(CSSPrimitiveValue::UnitTypePercentage))->value(); |
| - return createLength(pixels, percentage, hasPercentage, range); |
| -} |
| - |
| -Length CSSLengthInterpolationType::resolveInterpolableLength(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, const CSSToLengthConversionData& conversionData, ValueRange range) |
| -{ |
| - const InterpolableList& interpolableList = toInterpolableList(interpolableValue); |
| - bool hasPercentage = CSSLengthNonInterpolableValue::hasPercentage(nonInterpolableValue); |
| - double pixels = 0; |
| - double percentage = 0; |
| - for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| - double value = toInterpolableNumber(*interpolableList.get(i)).value(); |
| - if (i == CSSPrimitiveValue::UnitTypePercentage) { |
| - percentage = value; |
| - } else { |
| - CSSPrimitiveValue::UnitType type = CSSPrimitiveValue::lengthUnitTypeToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(i)); |
| - pixels += conversionData.zoomedComputedPixels(value, type); |
| - } |
| - } |
| - return createLength(pixels, percentage, hasPercentage, range); |
| -} |
| - |
| -static CSSPrimitiveValue::UnitType toUnitType(int lengthUnitType) |
| -{ |
| - return static_cast<CSSPrimitiveValue::UnitType>(CSSPrimitiveValue::lengthUnitTypeToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(lengthUnitType))); |
| -} |
| - |
| -static CSSCalcExpressionNode* createCalcExpression(const InterpolableList& values, bool hasPercentage) |
| -{ |
| - CSSCalcExpressionNode* result = nullptr; |
| - for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| - double value = toInterpolableNumber(values.get(i))->value(); |
| - if (value || (i == CSSPrimitiveValue::UnitTypePercentage && hasPercentage)) { |
| - CSSCalcExpressionNode* node = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(i))); |
| - result = result ? CSSCalcValue::createExpressionNode(result, node, CalcAdd) : node; |
| - } |
| - } |
| - DCHECK(result); |
| - return result; |
| -} |
| - |
| -static CSSValue* createCSSValue(const InterpolableList& values, bool hasPercentage, ValueRange range) |
| -{ |
| - size_t firstUnitIndex = CSSPrimitiveValue::LengthUnitTypeCount; |
| - size_t unitTypeCount = 0; |
| - for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| - if ((hasPercentage && i == CSSPrimitiveValue::UnitTypePercentage) || toInterpolableNumber(values.get(i))->value()) { |
| - unitTypeCount++; |
| - if (unitTypeCount == 1) |
| - firstUnitIndex = i; |
| - } |
| - } |
| - switch (unitTypeCount) { |
| - case 0: |
| - return CSSPrimitiveValue::create(0, CSSPrimitiveValue::UnitType::Pixels); |
| - case 1: { |
| - double value = clampToRange(toInterpolableNumber(values.get(firstUnitIndex))->value(), range); |
| - return CSSPrimitiveValue::create(value, toUnitType(firstUnitIndex)); |
| - } |
| - default: |
| - return CSSPrimitiveValue::create(CSSCalcValue::create(createCalcExpression(values, hasPercentage), range)); |
| - } |
| -} |
| - |
| void CSSLengthInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const |
|
suzyh_UTC10 (ex-contributor)
2016/08/29 07:12:31
Can you make the change to this function (and asso
alancutter (OOO until 2018)
2016/09/05 07:40:21
Done. https://codereview.chromium.org/2314453002
|
| { |
| StyleResolverState& state = environment.state(); |
| - const InterpolableList& values = toInterpolableList(interpolableValue); |
| - bool hasPercentage = CSSLengthNonInterpolableValue::hasPercentage(nonInterpolableValue); |
| - if (isPixelsOrPercentOnly(values)) { |
| - Length length = resolveInterpolablePixelsOrPercentageLength(values, hasPercentage, m_valueRange, effectiveZoom(*state.style())); |
| - if (LengthPropertyFunctions::setLength(cssProperty(), *state.style(), length)) { |
| + ComputedStyle& style = *state.style(); |
| + Length length = LengthInterpolationFunctions::createLength(interpolableValue, nonInterpolableValue, state.cssToLengthConversionData(), m_valueRange); |
| + if (LengthPropertyFunctions::setLength(cssProperty(), style, length)) { |
| #if DCHECK_IS_ON() |
| - // Assert that setting the length on ComputedStyle directly is identical to the AnimatableValue code path. |
| - RefPtr<AnimatableValue> before = CSSAnimatableValueFactory::create(cssProperty(), *state.style()); |
| - StyleBuilder::applyProperty(cssProperty(), state, *createCSSValue(values, hasPercentage, m_valueRange)); |
| - RefPtr<AnimatableValue> after = CSSAnimatableValueFactory::create(cssProperty(), *state.style()); |
| - DCHECK(before->equals(*after)); |
| + // Assert that setting the length on ComputedStyle directly is identical to the StyleBuilder code path. |
|
suzyh_UTC10 (ex-contributor)
2016/08/29 07:12:31
And in that separate patch, since you're already t
alancutter (OOO until 2018)
2016/09/05 07:40:22
Did B in https://codereview.chromium.org/231445300
|
| + // This check is useful for catching differences in clamping behaviour. |
| + RefPtr<AnimatableValue> before = CSSAnimatableValueFactory::create(cssProperty(), style); |
| + StyleBuilder::applyProperty(cssProperty(), environment.state(), *CSSPrimitiveValue::create(length, style.effectiveZoom())); |
| + RefPtr<AnimatableValue> after = CSSAnimatableValueFactory::create(cssProperty(), style); |
| + DCHECK(before->equals(*after)); |
| #endif |
| - return; |
| - } |
| + return; |
| } |
| - StyleBuilder::applyProperty(cssProperty(), state, *createCSSValue(values, hasPercentage, m_valueRange)); |
| + StyleBuilder::applyProperty(cssProperty(), state, *CSSPrimitiveValue::create(length, style.effectiveZoom())); |
| } |
| } // namespace blink |