Index: third_party/WebKit/Source/core/animation/CSSSizeListInterpolationType.cpp |
diff --git a/third_party/WebKit/Source/core/animation/CSSSizeListInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSSizeListInterpolationType.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d0e2446cd8ec79e8529424a586d26227e763c10d |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/animation/CSSSizeListInterpolationType.cpp |
@@ -0,0 +1,164 @@ |
+// 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/CSSSizeListInterpolationType.h" |
+ |
+#include "core/animation/ListInterpolationFunctions.h" |
+#include "core/animation/SizeInterpolationFunctions.h" |
+#include "core/animation/SizeListPropertyFunctions.h" |
+#include "core/css/CSSValueList.h" |
+#include "core/css/resolver/StyleResolverState.h" |
+ |
+namespace blink { |
+ |
+class UnderlyingSizeListChecker : public InterpolationType::ConversionChecker { |
+public: |
+ ~UnderlyingSizeListChecker() final {} |
+ |
+ static std::unique_ptr<UnderlyingSizeListChecker> create(const NonInterpolableList& underlyingList) |
+ { |
+ return wrapUnique(new UnderlyingSizeListChecker(underlyingList)); |
+ } |
+ |
+private: |
+ UnderlyingSizeListChecker(const NonInterpolableList& underlyingList) |
+ : m_underlyingList(&underlyingList) |
+ { } |
+ |
+ bool isValid(const InterpolationEnvironment&, const InterpolationValue& underlying) const final |
+ { |
+ const auto& underlyingList = toNonInterpolableList(*underlying.nonInterpolableValue); |
+ size_t underlyingLength = underlyingList.length(); |
+ if (underlyingLength != m_underlyingList->length()) |
+ return false; |
+ for (size_t i = 0; i < underlyingLength; i++) { |
+ bool compatible = SizeInterpolationFunctions::nonInterpolableValuesAreCompatible( |
+ underlyingList.get(i), m_underlyingList->get(i)); |
+ if (!compatible) |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ RefPtr<const NonInterpolableList> m_underlyingList; |
+}; |
+ |
+class InheritedSizeListChecker : public InterpolationType::ConversionChecker { |
+public: |
+ ~InheritedSizeListChecker() final {} |
+ |
+ static std::unique_ptr<InheritedSizeListChecker> create(CSSPropertyID property, const SizeList& inheritedSizeList) |
+ { |
+ return wrapUnique(new InheritedSizeListChecker(property, inheritedSizeList)); |
+ } |
+ |
+private: |
+ InheritedSizeListChecker(CSSPropertyID property, const SizeList& inheritedSizeList) |
+ : m_property(property) |
+ , m_inheritedSizeList(inheritedSizeList) |
+ { } |
+ |
+ bool isValid(const InterpolationEnvironment& environment, const InterpolationValue&) const final |
+ { |
+ return m_inheritedSizeList == SizeListPropertyFunctions::getSizeList(m_property, *environment.state().parentStyle()); |
+ } |
+ |
+ CSSPropertyID m_property; |
+ SizeList m_inheritedSizeList; |
+}; |
+ |
+InterpolationValue convertSizeList(const SizeList& sizeList, float zoom) |
+{ |
+ // Flatten pairs of width/height into individual items, even for contain and cover keywords. |
+ return ListInterpolationFunctions::createList(sizeList.size() * 2, [&sizeList, zoom](size_t index) -> InterpolationValue { |
+ bool convertWidth = index % 2 == 0; |
+ return SizeInterpolationFunctions::convertFillSizeSide(sizeList[index / 2], zoom, convertWidth); |
+ }); |
+} |
+ |
+InterpolationValue maybeConvertCSSSizeList(const CSSValue& value) |
+{ |
+ // CSSPropertyParser doesn't put single values in lists so wrap it up in a temporary list. |
+ const CSSValueList* list = nullptr; |
+ if (!value.isBaseValueList()) { |
+ CSSValueList* tempList = CSSValueList::createCommaSeparated(); |
+ tempList->append(value); |
+ list = tempList; |
+ } else { |
+ list = toCSSValueList(&value); |
+ } |
+ |
+ // Flatten pairs of width/height into individual items, even for contain and cover keywords. |
+ return ListInterpolationFunctions::createList(list->length() * 2, [list](size_t index) -> InterpolationValue { |
+ const CSSValue& cssSize = list->item(index / 2); |
+ bool convertWidth = index % 2 == 0; |
+ return SizeInterpolationFunctions::maybeConvertCSSSizeSide(cssSize, convertWidth); |
+ }); |
+} |
+ |
+InterpolationValue CSSSizeListInterpolationType::maybeConvertNeutral(const InterpolationValue& underlying, ConversionCheckers& conversionCheckers) const |
+{ |
+ const auto& underlyingList = toNonInterpolableList(*underlying.nonInterpolableValue); |
+ conversionCheckers.append(UnderlyingSizeListChecker::create(underlyingList)); |
+ return ListInterpolationFunctions::createList(underlyingList.length(), [&underlyingList](size_t index) { |
+ return SizeInterpolationFunctions::createNeutralValue(underlyingList.get(index)); |
+ }); |
+} |
+ |
+InterpolationValue CSSSizeListInterpolationType::maybeConvertInitial(const StyleResolverState&, ConversionCheckers&) const |
+{ |
+ return convertSizeList(SizeListPropertyFunctions::getInitialSizeList(cssProperty()), 1); |
+} |
+ |
+InterpolationValue CSSSizeListInterpolationType::maybeConvertInherit(const StyleResolverState& state, ConversionCheckers& conversionCheckers) const |
+{ |
+ SizeList inheritedSizeList = SizeListPropertyFunctions::getSizeList(cssProperty(), *state.parentStyle()); |
+ conversionCheckers.append(InheritedSizeListChecker::create(cssProperty(), inheritedSizeList)); |
+ return convertSizeList(inheritedSizeList, state.style()->effectiveZoom()); |
+} |
+ |
+InterpolationValue CSSSizeListInterpolationType::maybeConvertValue(const CSSValue& value, const StyleResolverState&, ConversionCheckers&) const |
+{ |
+ return maybeConvertCSSSizeList(value); |
+} |
+ |
+PairwiseInterpolationValue CSSSizeListInterpolationType::maybeMergeSingles(InterpolationValue&& start, InterpolationValue&& end) const |
+{ |
+ return ListInterpolationFunctions::maybeMergeSingles(std::move(start), std::move(end), SizeInterpolationFunctions::maybeMergeSingles); |
+} |
+ |
+InterpolationValue CSSSizeListInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const |
+{ |
+ const ComputedStyle& style = *environment.state().style(); |
+ return convertSizeList(SizeListPropertyFunctions::getSizeList(cssProperty(), style), style.effectiveZoom()); |
+} |
+ |
+void CSSSizeListInterpolationType::composite(UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationValue& value, double interpolationFraction) const |
+{ |
+ ListInterpolationFunctions::composite(underlyingValueOwner, underlyingFraction, *this, value, |
+ SizeInterpolationFunctions::nonInterpolableValuesAreCompatible, |
+ SizeInterpolationFunctions::composite); |
+} |
+ |
+void CSSSizeListInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const |
+{ |
+ const auto& interpolableList = toInterpolableList(interpolableValue); |
+ const auto& nonInterpolableList = toNonInterpolableList(*nonInterpolableValue); |
+ size_t length = interpolableList.length(); |
+ DCHECK_EQ(length, nonInterpolableList.length()); |
+ DCHECK_EQ(length % 2, 0ul); |
+ size_t sizeListLength = length / 2; |
+ SizeList sizeList(sizeListLength); |
+ for (size_t i = 0; i < sizeListLength; i++) { |
+ sizeList[i] = SizeInterpolationFunctions::createFillSize( |
+ *interpolableList.get(i * 2), |
+ nonInterpolableList.get(i * 2), |
+ *interpolableList.get(i * 2 + 1), |
+ nonInterpolableList.get(i * 2 + 1), |
+ environment.state().cssToLengthConversionData()); |
+ } |
+ SizeListPropertyFunctions::setSizeList(cssProperty(), *environment.state().style(), sizeList); |
+} |
+ |
+} // namespace blink |