Index: third_party/WebKit/Source/core/animation/CSSClipInterpolationType.cpp |
diff --git a/third_party/WebKit/Source/core/animation/CSSClipInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSClipInterpolationType.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..98328de40cde73705361096b3a240f54d936313b |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/animation/CSSClipInterpolationType.cpp |
@@ -0,0 +1,265 @@ |
+// 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/CSSClipInterpolationType.h" |
+ |
+#include "core/animation/CSSLengthInterpolationType.h" |
+#include "core/css/CSSQuadValue.h" |
+#include "core/css/resolver/StyleResolverState.h" |
+ |
+namespace blink { |
+ |
+struct ClipAutos { |
+ ClipAutos() |
+ : isAuto(true) |
+ , isTopAuto(false) |
+ , isRightAuto(false) |
+ , isBottomAuto(false) |
+ , isLeftAuto(false) |
+ { } |
+ ClipAutos(bool isTopAuto, bool isRightAuto, bool isBottomAuto, bool isLeftAuto) |
+ : isAuto(false) |
+ , isTopAuto(isTopAuto) |
+ , isRightAuto(isRightAuto) |
+ , isBottomAuto(isBottomAuto) |
+ , isLeftAuto(isLeftAuto) |
+ { } |
+ ClipAutos(const LengthBox& clip) |
Eric Willigers
2016/02/17 12:09:53
Perhaps this can be explicit.
alancutter (OOO until 2018)
2016/02/17 23:44:34
Done.
|
+ : isAuto(false) |
+ , isTopAuto(clip.top().isAuto()) |
+ , isRightAuto(clip.right().isAuto()) |
+ , isBottomAuto(clip.bottom().isAuto()) |
+ , isLeftAuto(clip.left().isAuto()) |
+ { } |
+ |
+ bool operator==(const ClipAutos& other) const |
+ { |
+ return isAuto == other.isAuto |
+ && isTopAuto == other.isTopAuto |
+ && isRightAuto == other.isRightAuto |
+ && isBottomAuto == other.isBottomAuto |
+ && isLeftAuto == other.isLeftAuto; |
+ } |
+ bool operator!=(const ClipAutos& other) const { return !(*this == other); } |
+ |
+ bool isAuto; |
+ bool isTopAuto; |
+ bool isRightAuto; |
+ bool isBottomAuto; |
+ bool isLeftAuto; |
+}; |
+ |
+static ClipAutos getClipAutos(const ComputedStyle& style) |
+{ |
+ if (style.hasAutoClip()) |
+ return ClipAutos(); |
+ return ClipAutos( |
+ style.clipTop().isAuto(), |
+ style.clipRight().isAuto(), |
+ style.clipBottom().isAuto(), |
+ style.clipLeft().isAuto()); |
+} |
+ |
+class ParentAutosChecker : public InterpolationType::ConversionChecker { |
+public: |
+ static PassOwnPtr<ParentAutosChecker> create(const ClipAutos& parentAutos) |
+ { |
+ return adoptPtr(new ParentAutosChecker(parentAutos)); |
+ } |
+ |
+private: |
+ ParentAutosChecker(const ClipAutos& parentAutos) |
+ : m_parentAutos(parentAutos) |
+ { } |
+ |
+ bool isValid(const InterpolationEnvironment& environment, const InterpolationValue& underlying) const final |
+ { |
+ return m_parentAutos == getClipAutos(*environment.state().parentStyle()); |
+ } |
+ |
+ const ClipAutos m_parentAutos; |
+}; |
+ |
+class CSSClipNonInterpolableValue : public NonInterpolableValue { |
+public: |
+ ~CSSClipNonInterpolableValue() final { } |
+ |
+ static PassRefPtr<CSSClipNonInterpolableValue> create(const ClipAutos& clipAutos) |
+ { |
+ return adoptRef(new CSSClipNonInterpolableValue(clipAutos)); |
+ } |
+ |
+ const ClipAutos& clipAutos() const { return m_clipAutos; } |
+ |
+ DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
+ |
+private: |
+ CSSClipNonInterpolableValue(const ClipAutos& clipAutos) |
+ : m_clipAutos(clipAutos) |
+ { |
+ ASSERT(!m_clipAutos.isAuto); |
+ } |
+ |
+ const ClipAutos m_clipAutos; |
+}; |
+ |
+DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSClipNonInterpolableValue); |
+DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSClipNonInterpolableValue); |
+ |
+class UnderlyingAutosChecker : public InterpolationType::ConversionChecker { |
+public: |
+ ~UnderlyingAutosChecker() final {} |
+ |
+ static PassOwnPtr<UnderlyingAutosChecker> create(const ClipAutos& underlyingAutos) |
+ { |
+ return adoptPtr(new UnderlyingAutosChecker(underlyingAutos)); |
+ } |
+ |
+ static ClipAutos getUnderlyingAutos(const InterpolationValue& underlying) |
+ { |
+ if (!underlying) |
+ return ClipAutos(); |
+ return toCSSClipNonInterpolableValue(*underlying.nonInterpolableValue).clipAutos(); |
+ } |
+ |
+private: |
+ UnderlyingAutosChecker(const ClipAutos& underlyingAutos) |
+ : m_underlyingAutos(underlyingAutos) |
+ { } |
+ |
+ bool isValid(const InterpolationEnvironment&, const InterpolationValue& underlying) const final |
+ { |
+ return m_underlyingAutos == getUnderlyingAutos(underlying); |
+ } |
+ |
+ const ClipAutos m_underlyingAutos; |
+}; |
+ |
+enum ClipComponentIndex { |
+ ClipTop, |
+ ClipRight, |
+ ClipBottom, |
+ ClipLeft, |
+ ClipComponentIndexCount, |
+}; |
+ |
+static PassOwnPtr<InterpolableValue> convertClipComponent(const Length& length, double zoom) |
+{ |
+ if (length.isAuto()) |
+ return InterpolableList::create(0); |
+ return CSSLengthInterpolationType::maybeConvertLength(length, zoom).interpolableValue.release(); |
+} |
+ |
+static InterpolationValue createClipValue(const LengthBox& clip, double zoom) |
+{ |
+ OwnPtr<InterpolableList> list = InterpolableList::create(ClipComponentIndexCount); |
+ list->set(ClipTop, convertClipComponent(clip.top(), zoom)); |
+ list->set(ClipRight, convertClipComponent(clip.right(), zoom)); |
+ list->set(ClipBottom, convertClipComponent(clip.bottom(), zoom)); |
+ list->set(ClipLeft, convertClipComponent(clip.left(), zoom)); |
+ return InterpolationValue(list.release(), CSSClipNonInterpolableValue::create(ClipAutos(clip))); |
+} |
+ |
+InterpolationValue CSSClipInterpolationType::maybeConvertNeutral(const InterpolationValue& underlying, ConversionCheckers& conversionCheckers) const |
+{ |
+ ClipAutos underlyingAutos = UnderlyingAutosChecker::getUnderlyingAutos(underlying); |
+ conversionCheckers.append(UnderlyingAutosChecker::create(underlyingAutos)); |
+ if (underlyingAutos.isAuto) |
+ return nullptr; |
+ LengthBox neutralBox( |
+ underlyingAutos.isTopAuto ? Length(Auto) : Length(0, Fixed), |
+ underlyingAutos.isRightAuto ? Length(Auto) : Length(0, Fixed), |
+ underlyingAutos.isBottomAuto ? Length(Auto) : Length(0, Fixed), |
+ underlyingAutos.isLeftAuto ? Length(Auto) : Length(0, Fixed)); |
+ return createClipValue(neutralBox, 1); |
+} |
+ |
+InterpolationValue CSSClipInterpolationType::maybeConvertInitial() const |
+{ |
+ return nullptr; |
+} |
+ |
+InterpolationValue CSSClipInterpolationType::maybeConvertInherit(const StyleResolverState& state, ConversionCheckers& conversionCheckers) const |
+{ |
+ ClipAutos parentAutos = getClipAutos(*state.parentStyle()); |
+ conversionCheckers.append(ParentAutosChecker::create(parentAutos)); |
+ if (parentAutos.isAuto) |
+ return nullptr; |
+ return createClipValue(state.parentStyle()->clip(), state.parentStyle()->effectiveZoom()); |
+} |
+ |
+static bool isCSSAuto(const CSSPrimitiveValue& value) |
+{ |
+ return value.getValueID() == CSSValueAuto; |
+} |
+ |
+static PassOwnPtr<InterpolableValue> convertClipComponent(const CSSPrimitiveValue& length) |
+{ |
+ if (isCSSAuto(length)) |
+ return InterpolableList::create(0); |
+ return CSSLengthInterpolationType::maybeConvertCSSValue(length).interpolableValue.release(); |
+} |
+ |
+InterpolationValue CSSClipInterpolationType::maybeConvertValue(const CSSValue& value, const StyleResolverState& state, ConversionCheckers&) const |
+{ |
+ if (!value.isQuadValue()) |
+ return nullptr; |
+ const CSSQuadValue& quad = toCSSQuadValue(value); |
+ OwnPtr<InterpolableList> list = InterpolableList::create(ClipComponentIndexCount); |
+ list->set(ClipTop, convertClipComponent(*quad.top())); |
+ list->set(ClipRight, convertClipComponent(*quad.right())); |
+ list->set(ClipBottom, convertClipComponent(*quad.bottom())); |
+ list->set(ClipLeft, convertClipComponent(*quad.left())); |
+ ClipAutos autos( |
+ isCSSAuto(*quad.top()), |
+ isCSSAuto(*quad.right()), |
+ isCSSAuto(*quad.bottom()), |
+ isCSSAuto(*quad.left())); |
+ return InterpolationValue(list.release(), CSSClipNonInterpolableValue::create(autos)); |
+} |
+ |
+InterpolationValue CSSClipInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const |
+{ |
+ if (environment.state().style()->hasAutoClip()) |
+ return nullptr; |
+ return createClipValue(environment.state().style()->clip(), environment.state().style()->effectiveZoom()); |
+} |
+ |
+PairwiseInterpolationValue CSSClipInterpolationType::mergeSingleConversions(InterpolationValue& start, InterpolationValue& end) const |
+{ |
+ const ClipAutos& startAutos = toCSSClipNonInterpolableValue(*start.nonInterpolableValue).clipAutos(); |
+ const ClipAutos& endAutos = toCSSClipNonInterpolableValue(*end.nonInterpolableValue).clipAutos(); |
+ if (startAutos != endAutos) |
+ return nullptr; |
+ return PairwiseInterpolationValue(start.interpolableValue.release(), end.interpolableValue.release(), start.nonInterpolableValue.release()); |
+} |
+ |
+void CSSClipInterpolationType::composite(UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationValue& value) const |
+{ |
+ const ClipAutos& underlyingAutos = toCSSClipNonInterpolableValue(*underlyingValueOwner.value().nonInterpolableValue).clipAutos(); |
+ const ClipAutos& autos = toCSSClipNonInterpolableValue(*value.nonInterpolableValue).clipAutos(); |
+ if (underlyingAutos == autos) |
+ underlyingValueOwner.mutableValue().interpolableValue->scaleAndAdd(underlyingFraction, *value.interpolableValue); |
+ else |
+ underlyingValueOwner.set(*this, value); |
+} |
+ |
+void CSSClipInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const |
+{ |
+ const ClipAutos& autos = toCSSClipNonInterpolableValue(nonInterpolableValue)->clipAutos(); |
+ const InterpolableList& list = toInterpolableList(interpolableValue); |
+ const auto& convertIndex = [&list, &environment](bool isAuto, size_t index) |
+ { |
+ if (isAuto) |
+ return Length(Auto); |
+ return CSSLengthInterpolationType::resolveInterpolableLength(*list.get(index), nullptr, environment.state().cssToLengthConversionData(), ValueRangeAll); |
+ }; |
+ environment.state().style()->setClip(LengthBox( |
+ convertIndex(autos.isTopAuto, ClipTop), |
+ convertIndex(autos.isRightAuto, ClipRight), |
+ convertIndex(autos.isBottomAuto, ClipBottom), |
+ convertIndex(autos.isLeftAuto, ClipLeft))); |
+} |
+ |
+} // namespace blink |