Chromium Code Reviews| Index: third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp |
| diff --git a/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..505ab0c45ef1c35cf7ca8ff82442de5979222ecb |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/animation/SizeInterpolationFunctions.cpp |
| @@ -0,0 +1,186 @@ |
| +// Copyright 2016 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 "core/animation/SizeInterpolationFunctions.h" |
| + |
| +#include "core/animation/LengthInterpolationFunctions.h" |
| +#include "core/animation/UnderlyingValueOwner.h" |
| +#include "core/css/CSSToLengthConversionData.h" |
| +#include "core/css/CSSValuePair.h" |
| + |
| +namespace blink { |
| + |
| +class CSSSizeNonInterpolableValue : public NonInterpolableValue { |
| +public: |
| + static PassRefPtr<CSSSizeNonInterpolableValue> create(CSSValueID keyword) |
| + { |
| + return adoptRef(new CSSSizeNonInterpolableValue(keyword)); |
| + } |
| + |
| + static PassRefPtr<CSSSizeNonInterpolableValue> create(PassRefPtr<NonInterpolableValue> lengthNonInterpolableValue) |
| + { |
| + return adoptRef(new CSSSizeNonInterpolableValue(lengthNonInterpolableValue)); |
| + } |
| + |
| + bool isKeyword() const { return m_keyword != CSSValueInvalid; } |
| + CSSValueID keyword() const { DCHECK(isKeyword()); return m_keyword; } |
| + |
| + const NonInterpolableValue* lengthNonInterpolableValue() const { DCHECK(!isKeyword()); return m_lengthNonInterpolableValue.get(); } |
| + RefPtr<NonInterpolableValue>& lengthNonInterpolableValue() { DCHECK(!isKeyword()); return m_lengthNonInterpolableValue; } |
| + |
| + DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
| + |
| +private: |
| + CSSSizeNonInterpolableValue(CSSValueID keyword) |
| + : m_keyword(keyword) |
| + , m_lengthNonInterpolableValue(nullptr) |
| + { |
| + DCHECK_NE(keyword, CSSValueInvalid); |
| + } |
| + |
| + CSSSizeNonInterpolableValue(PassRefPtr<NonInterpolableValue> lengthNonInterpolableValue) |
| + : m_keyword(CSSValueInvalid) |
| + , m_lengthNonInterpolableValue(lengthNonInterpolableValue) |
| + { } |
|
Eric Willigers
2016/08/31 01:47:06
DCHECK(m_lengthNonInterpolableValue);
alancutter (OOO until 2018)
2016/09/05 07:44:27
Done.
alancutter (OOO until 2018)
2016/09/06 02:27:31
Whoops, that's actually allowed to be nullptr. Rem
|
| + |
| + CSSValueID m_keyword; |
| + RefPtr<NonInterpolableValue> m_lengthNonInterpolableValue; |
| +}; |
| + |
| +DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSSizeNonInterpolableValue); |
| +DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSSizeNonInterpolableValue); |
| + |
| +static InterpolationValue convertKeyword(CSSValueID keyword) |
| +{ |
| + return InterpolationValue(InterpolableList::create(0), CSSSizeNonInterpolableValue::create(keyword)); |
| +} |
| + |
| +static InterpolationValue wrapConvertedLength(InterpolationValue&& convertedLength) |
| +{ |
| + if (!convertedLength) |
| + return nullptr; |
| + return InterpolationValue( |
| + std::move(convertedLength.interpolableValue), |
| + CSSSizeNonInterpolableValue::create(convertedLength.nonInterpolableValue.release())); |
| +} |
| + |
| +InterpolationValue SizeInterpolationFunctions::convertFillSizeSide(const FillSize& fillSize, float zoom, bool convertWidth) |
| +{ |
| + switch (fillSize.type) { |
| + case SizeLength: { |
| + const Length& side = convertWidth ? fillSize.size.width() : fillSize.size.height(); |
| + if (side.isAuto()) |
| + return convertKeyword(CSSValueAuto); |
| + return wrapConvertedLength(LengthInterpolationFunctions::maybeConvertLength(side, zoom)); |
| + } |
| + case Contain: |
| + return convertKeyword(CSSValueContain); |
| + case Cover: |
| + return convertKeyword(CSSValueCover); |
| + case SizeNone: |
| + default: |
| + NOTREACHED(); |
| + return nullptr; |
| + } |
| +} |
| + |
| +InterpolationValue SizeInterpolationFunctions::maybeConvertCSSSizeSide(const CSSValue& value, bool convertWidth) |
| +{ |
| + if (value.isValuePair()) { |
| + const CSSValuePair& pair = toCSSValuePair(value); |
| + const CSSValue& side = convertWidth ? pair.first() : pair.second(); |
| + if (side.isPrimitiveValue() && toCSSPrimitiveValue(side).getValueID() == CSSValueAuto) |
| + return convertKeyword(CSSValueAuto); |
| + return wrapConvertedLength(LengthInterpolationFunctions::maybeConvertCSSValue(side)); |
| + } |
| + |
| + if (!value.isPrimitiveValue()) |
| + return nullptr; |
| + CSSValueID keyword = toCSSPrimitiveValue(value).getValueID(); |
| + if (keyword) |
| + return convertKeyword(keyword); |
| + |
| + // A single length is equivalent to "<length> auto". |
| + if (convertWidth) |
| + return wrapConvertedLength(LengthInterpolationFunctions::maybeConvertCSSValue(value)); |
| + return convertKeyword(CSSValueAuto); |
| +} |
| + |
| +PairwiseInterpolationValue SizeInterpolationFunctions::maybeMergeSingles(InterpolationValue&& start, InterpolationValue&& end) |
| +{ |
| + if (!nonInterpolableValuesAreCompatible(start.nonInterpolableValue.get(), end.nonInterpolableValue.get())) |
| + return nullptr; |
| + return PairwiseInterpolationValue( |
| + std::move(start.interpolableValue), |
| + std::move(end.interpolableValue), |
| + start.nonInterpolableValue.release()); |
| +} |
| + |
| +InterpolationValue SizeInterpolationFunctions::createNeutralValue(const NonInterpolableValue* nonInterpolableValue) |
| +{ |
| + auto& size = toCSSSizeNonInterpolableValue(*nonInterpolableValue); |
| + if (size.isKeyword()) |
| + return convertKeyword(size.keyword()); |
| + return wrapConvertedLength(InterpolationValue(LengthInterpolationFunctions::createNeutralInterpolableValue())); |
| +} |
| + |
| +bool SizeInterpolationFunctions::nonInterpolableValuesAreCompatible(const NonInterpolableValue* a, const NonInterpolableValue* b) |
| +{ |
| + const auto& sizeA = toCSSSizeNonInterpolableValue(*a); |
| + const auto& sizeB = toCSSSizeNonInterpolableValue(*b); |
| + if (sizeA.isKeyword() != sizeB.isKeyword()) |
| + return false; |
| + if (sizeA.isKeyword()) |
| + return sizeA.keyword() == sizeB.keyword(); |
| + return true; |
| +} |
| + |
| +void SizeInterpolationFunctions::composite(std::unique_ptr<InterpolableValue>& underlyingInterpolableValue, RefPtr<NonInterpolableValue>& underlyingNonInterpolableValue, double underlyingFraction, const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) |
| +{ |
| + const auto& sizeNonInterpolableValue = toCSSSizeNonInterpolableValue(*nonInterpolableValue); |
| + if (sizeNonInterpolableValue.isKeyword()) |
| + return; |
| + auto& underlyingSizeNonInterpolableValue = toCSSSizeNonInterpolableValue(*underlyingNonInterpolableValue); |
| + LengthInterpolationFunctions::composite( |
| + underlyingInterpolableValue, |
| + underlyingSizeNonInterpolableValue.lengthNonInterpolableValue(), |
| + underlyingFraction, |
| + interpolableValue, |
| + sizeNonInterpolableValue.lengthNonInterpolableValue()); |
| +} |
| + |
| +static Length createLength(const InterpolableValue& interpolableValue, const CSSSizeNonInterpolableValue& nonInterpolableValue, const CSSToLengthConversionData& conversionData) |
| +{ |
| + if (nonInterpolableValue.isKeyword()) { |
| + DCHECK_EQ(nonInterpolableValue.keyword(), CSSValueAuto); |
| + return Length(Auto); |
| + } |
| + return LengthInterpolationFunctions::createLength(interpolableValue, nonInterpolableValue.lengthNonInterpolableValue(), conversionData, ValueRangeNonNegative); |
| +} |
| + |
| +FillSize SizeInterpolationFunctions::createFillSize(const InterpolableValue& interpolableValueA, const NonInterpolableValue* nonInterpolableValueA, const InterpolableValue& interpolableValueB, const NonInterpolableValue* nonInterpolableValueB, const CSSToLengthConversionData& conversionData) |
| +{ |
| + const auto& sideA = toCSSSizeNonInterpolableValue(*nonInterpolableValueA); |
| + const auto& sideB = toCSSSizeNonInterpolableValue(*nonInterpolableValueB); |
| + if (sideA.isKeyword()) { |
| + switch (sideA.keyword()) { |
| + case CSSValueCover: |
| + DCHECK_EQ(sideA.keyword(), sideB.keyword()); |
| + return FillSize(Cover, LengthSize()); |
| + case CSSValueContain: |
| + DCHECK_EQ(sideA.keyword(), sideB.keyword()); |
| + return FillSize(Contain, LengthSize()); |
| + case CSSValueAuto: |
| + break; |
| + default: |
| + NOTREACHED(); |
| + break; |
| + } |
| + } |
| + return FillSize(SizeLength, LengthSize( |
| + createLength(interpolableValueA, sideA, conversionData), |
| + createLength(interpolableValueB, sideB, conversionData))); |
| +} |
| + |
| +} // namespace blink |