Index: third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp |
diff --git a/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp |
index 9625b29a1e364c88aa653b867af7573c5d8a4cbe..f9b781a5b6b9ec28426a4ac8dedbc1aa8cb73b84 100644 |
--- a/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp |
+++ b/third_party/WebKit/Source/core/animation/CSSBorderImageLengthBoxInterpolationType.cpp |
@@ -4,12 +4,13 @@ |
#include "core/animation/CSSBorderImageLengthBoxInterpolationType.h" |
+#include <memory> |
#include "core/animation/BorderImageLengthBoxPropertyFunctions.h" |
#include "core/animation/LengthInterpolationFunctions.h" |
+#include "core/css/CSSIdentifierValue.h" |
#include "core/css/CSSQuadValue.h" |
#include "core/css/resolver/StyleResolverState.h" |
#include "wtf/PtrUtil.h" |
-#include <memory> |
namespace blink { |
@@ -23,34 +24,58 @@ enum SideIndex : unsigned { |
SideIndexCount, |
}; |
-struct SideNumbers { |
- explicit SideNumbers(const BorderImageLengthBox& box) { |
- isNumber[SideTop] = box.top().isNumber(); |
- isNumber[SideRight] = box.right().isNumber(); |
- isNumber[SideBottom] = box.bottom().isNumber(); |
- isNumber[SideLeft] = box.left().isNumber(); |
+enum class SideType { |
+ Number, |
+ Auto, |
+ Length, |
+}; |
+ |
+SideType getSideType(const BorderImageLength& side) { |
+ if (side.isNumber()) { |
+ return SideType::Number; |
+ } |
+ if (side.length().isAuto()) { |
+ return SideType::Auto; |
+ } |
+ DCHECK(side.length().isSpecified()); |
+ return SideType::Length; |
+} |
+ |
+SideType getSideType(const CSSValue& side) { |
+ if (side.isPrimitiveValue() && toCSSPrimitiveValue(side).isNumber()) { |
+ return SideType::Number; |
+ } |
+ if (side.isIdentifierValue() && |
+ toCSSIdentifierValue(side).getValueID() == CSSValueAuto) { |
+ return SideType::Auto; |
+ } |
+ return SideType::Length; |
+} |
+ |
+struct SideTypes { |
+ explicit SideTypes(const BorderImageLengthBox& box) { |
+ type[SideTop] = getSideType(box.top()); |
+ type[SideRight] = getSideType(box.right()); |
+ type[SideBottom] = getSideType(box.bottom()); |
+ type[SideLeft] = getSideType(box.left()); |
} |
- explicit SideNumbers(const CSSQuadValue& quad) { |
- isNumber[SideTop] = quad.top()->isPrimitiveValue() && |
- toCSSPrimitiveValue(quad.top())->isNumber(); |
- isNumber[SideRight] = quad.right()->isPrimitiveValue() && |
- toCSSPrimitiveValue(quad.right())->isNumber(); |
- isNumber[SideBottom] = quad.bottom()->isPrimitiveValue() && |
- toCSSPrimitiveValue(quad.bottom())->isNumber(); |
- isNumber[SideLeft] = quad.left()->isPrimitiveValue() && |
- toCSSPrimitiveValue(quad.left())->isNumber(); |
+ explicit SideTypes(const CSSQuadValue& quad) { |
+ type[SideTop] = getSideType(*quad.top()); |
+ type[SideRight] = getSideType(*quad.right()); |
+ type[SideBottom] = getSideType(*quad.bottom()); |
+ type[SideLeft] = getSideType(*quad.left()); |
} |
- bool operator==(const SideNumbers& other) const { |
+ bool operator==(const SideTypes& other) const { |
for (size_t i = 0; i < SideIndexCount; i++) { |
- if (isNumber[i] != other.isNumber[i]) |
+ if (type[i] != other.type[i]) |
return false; |
} |
return true; |
} |
- bool operator!=(const SideNumbers& other) const { return !(*this == other); } |
+ bool operator!=(const SideTypes& other) const { return !(*this == other); } |
- bool isNumber[SideIndexCount]; |
+ SideType type[SideIndexCount]; |
}; |
} // namespace |
@@ -59,13 +84,19 @@ class CSSBorderImageLengthBoxNonInterpolableValue |
: public NonInterpolableValue { |
public: |
static PassRefPtr<CSSBorderImageLengthBoxNonInterpolableValue> create( |
- const SideNumbers& sideNumbers, |
+ const SideTypes& sideTypes, |
Vector<RefPtr<NonInterpolableValue>>&& sideNonInterpolableValues) { |
return adoptRef(new CSSBorderImageLengthBoxNonInterpolableValue( |
- sideNumbers, std::move(sideNonInterpolableValues))); |
+ sideTypes, std::move(sideNonInterpolableValues))); |
+ } |
+ |
+ PassRefPtr<CSSBorderImageLengthBoxNonInterpolableValue> clone() { |
+ return adoptRef(new CSSBorderImageLengthBoxNonInterpolableValue( |
+ m_sideTypes, |
+ Vector<RefPtr<NonInterpolableValue>>(m_sideNonInterpolableValues))); |
} |
- const SideNumbers& sideNumbers() const { return m_sideNumbers; } |
+ const SideTypes& sideTypes() const { return m_sideTypes; } |
const Vector<RefPtr<NonInterpolableValue>>& sideNonInterpolableValues() |
const { |
return m_sideNonInterpolableValues; |
@@ -78,14 +109,14 @@ class CSSBorderImageLengthBoxNonInterpolableValue |
private: |
CSSBorderImageLengthBoxNonInterpolableValue( |
- const SideNumbers& sideNumbers, |
+ const SideTypes& sideTypes, |
Vector<RefPtr<NonInterpolableValue>>&& sideNonInterpolableValues) |
- : m_sideNumbers(sideNumbers), |
+ : m_sideTypes(sideTypes), |
m_sideNonInterpolableValues(sideNonInterpolableValues) { |
DCHECK_EQ(m_sideNonInterpolableValues.size(), SideIndexCount); |
} |
- const SideNumbers m_sideNumbers; |
+ const SideTypes m_sideTypes; |
Vector<RefPtr<NonInterpolableValue>> m_sideNonInterpolableValues; |
}; |
@@ -95,59 +126,56 @@ DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS( |
namespace { |
-class UnderlyingSideNumbersChecker |
- : public InterpolationType::ConversionChecker { |
+class UnderlyingSideTypesChecker : public InterpolationType::ConversionChecker { |
public: |
- static std::unique_ptr<UnderlyingSideNumbersChecker> create( |
- const SideNumbers& underlyingSideNumbers) { |
- return WTF::wrapUnique( |
- new UnderlyingSideNumbersChecker(underlyingSideNumbers)); |
+ static std::unique_ptr<UnderlyingSideTypesChecker> create( |
+ const SideTypes& underlyingSideTypes) { |
+ return WTF::wrapUnique(new UnderlyingSideTypesChecker(underlyingSideTypes)); |
} |
- static SideNumbers getUnderlyingSideNumbers( |
+ static SideTypes getUnderlyingSideTypes( |
const InterpolationValue& underlying) { |
return toCSSBorderImageLengthBoxNonInterpolableValue( |
*underlying.nonInterpolableValue) |
- .sideNumbers(); |
+ .sideTypes(); |
} |
private: |
- UnderlyingSideNumbersChecker(const SideNumbers& underlyingSideNumbers) |
- : m_underlyingSideNumbers(underlyingSideNumbers) {} |
+ UnderlyingSideTypesChecker(const SideTypes& underlyingSideTypes) |
+ : m_underlyingSideTypes(underlyingSideTypes) {} |
bool isValid(const InterpolationEnvironment&, |
const InterpolationValue& underlying) const final { |
- return m_underlyingSideNumbers == getUnderlyingSideNumbers(underlying); |
+ return m_underlyingSideTypes == getUnderlyingSideTypes(underlying); |
} |
- const SideNumbers m_underlyingSideNumbers; |
+ const SideTypes m_underlyingSideTypes; |
}; |
-class InheritedSideNumbersChecker |
- : public InterpolationType::ConversionChecker { |
+class InheritedSideTypesChecker : public InterpolationType::ConversionChecker { |
public: |
- static std::unique_ptr<InheritedSideNumbersChecker> create( |
+ static std::unique_ptr<InheritedSideTypesChecker> create( |
CSSPropertyID property, |
- const SideNumbers& inheritedSideNumbers) { |
+ const SideTypes& inheritedSideTypes) { |
return WTF::wrapUnique( |
- new InheritedSideNumbersChecker(property, inheritedSideNumbers)); |
+ new InheritedSideTypesChecker(property, inheritedSideTypes)); |
} |
private: |
- InheritedSideNumbersChecker(CSSPropertyID property, |
- const SideNumbers& inheritedSideNumbers) |
- : m_property(property), m_inheritedSideNumbers(inheritedSideNumbers) {} |
+ InheritedSideTypesChecker(CSSPropertyID property, |
+ const SideTypes& inheritedSideTypes) |
+ : m_property(property), m_inheritedSideTypes(inheritedSideTypes) {} |
bool isValid(const InterpolationEnvironment& environment, |
const InterpolationValue& underlying) const final { |
- return m_inheritedSideNumbers == |
- SideNumbers( |
+ return m_inheritedSideTypes == |
+ SideTypes( |
BorderImageLengthBoxPropertyFunctions::getBorderImageLengthBox( |
m_property, *environment.state().parentStyle())); |
} |
const CSSPropertyID m_property; |
- const SideNumbers m_inheritedSideNumbers; |
+ const SideTypes m_inheritedSideTypes; |
}; |
InterpolationValue convertBorderImageLengthBox(const BorderImageLengthBox& box, |
@@ -165,6 +193,8 @@ InterpolationValue convertBorderImageLengthBox(const BorderImageLengthBox& box, |
const BorderImageLength& side = *sides[i]; |
if (side.isNumber()) { |
list->set(i, InterpolableNumber::create(side.number())); |
+ } else if (side.length().isAuto()) { |
+ list->set(i, InterpolableList::create(0)); |
} else { |
InterpolationValue convertedSide = |
LengthInterpolationFunctions::maybeConvertLength(side.length(), zoom); |
@@ -177,7 +207,7 @@ InterpolationValue convertBorderImageLengthBox(const BorderImageLengthBox& box, |
return InterpolationValue( |
std::move(list), CSSBorderImageLengthBoxNonInterpolableValue::create( |
- SideNumbers(box), std::move(nonInterpolableValues))); |
+ SideTypes(box), std::move(nonInterpolableValues))); |
} |
} // namespace |
@@ -186,18 +216,14 @@ InterpolationValue |
CSSBorderImageLengthBoxInterpolationType::maybeConvertNeutral( |
const InterpolationValue& underlying, |
ConversionCheckers& conversionCheckers) const { |
- SideNumbers underlyingSideNumbers = |
- UnderlyingSideNumbersChecker::getUnderlyingSideNumbers(underlying); |
+ SideTypes underlyingSideTypes = |
+ UnderlyingSideTypesChecker::getUnderlyingSideTypes(underlying); |
conversionCheckers.push_back( |
- UnderlyingSideNumbersChecker::create(underlyingSideNumbers)); |
- const auto& zero = [&underlyingSideNumbers](size_t index) { |
- return underlyingSideNumbers.isNumber[index] |
- ? BorderImageLength(0) |
- : BorderImageLength(Length(0, Fixed)); |
- }; |
- BorderImageLengthBox zeroBox(zero(SideTop), zero(SideRight), zero(SideBottom), |
- zero(SideLeft)); |
- return convertBorderImageLengthBox(zeroBox, 1); |
+ UnderlyingSideTypesChecker::create(underlyingSideTypes)); |
+ return InterpolationValue(underlying.interpolableValue->cloneAndZero(), |
+ toCSSBorderImageLengthBoxNonInterpolableValue( |
+ *underlying.nonInterpolableValue) |
+ .clone()); |
} |
InterpolationValue |
@@ -217,8 +243,8 @@ CSSBorderImageLengthBoxInterpolationType::maybeConvertInherit( |
const BorderImageLengthBox& inherited = |
BorderImageLengthBoxPropertyFunctions::getBorderImageLengthBox( |
cssProperty(), *state.parentStyle()); |
- conversionCheckers.push_back(InheritedSideNumbersChecker::create( |
- cssProperty(), SideNumbers(inherited))); |
+ conversionCheckers.push_back( |
+ InheritedSideTypesChecker::create(cssProperty(), SideTypes(inherited))); |
return convertBorderImageLengthBox(inherited, |
state.parentStyle()->effectiveZoom()); |
} |
@@ -245,6 +271,9 @@ InterpolationValue CSSBorderImageLengthBoxInterpolationType::maybeConvertValue( |
if (side.isPrimitiveValue() && toCSSPrimitiveValue(side).isNumber()) { |
list->set(i, InterpolableNumber::create( |
toCSSPrimitiveValue(side).getDoubleValue())); |
+ } else if (side.isIdentifierValue() && |
+ toCSSIdentifierValue(side).getValueID() == CSSValueAuto) { |
+ list->set(i, InterpolableList::create(0)); |
} else { |
InterpolationValue convertedSide = |
LengthInterpolationFunctions::maybeConvertCSSValue(side); |
@@ -256,9 +285,8 @@ InterpolationValue CSSBorderImageLengthBoxInterpolationType::maybeConvertValue( |
} |
return InterpolationValue( |
- std::move(list), |
- CSSBorderImageLengthBoxNonInterpolableValue::create( |
- SideNumbers(quad), std::move(nonInterpolableValues))); |
+ std::move(list), CSSBorderImageLengthBoxNonInterpolableValue::create( |
+ SideTypes(quad), std::move(nonInterpolableValues))); |
} |
InterpolationValue CSSBorderImageLengthBoxInterpolationType:: |
@@ -274,14 +302,13 @@ PairwiseInterpolationValue |
CSSBorderImageLengthBoxInterpolationType::maybeMergeSingles( |
InterpolationValue&& start, |
InterpolationValue&& end) const { |
- const SideNumbers& startSideNumbers = |
+ const SideTypes& startSideTypes = |
toCSSBorderImageLengthBoxNonInterpolableValue(*start.nonInterpolableValue) |
- .sideNumbers(); |
- const SideNumbers& endSideNumbers = |
+ .sideTypes(); |
+ const SideTypes& endSideTypes = |
toCSSBorderImageLengthBoxNonInterpolableValue(*end.nonInterpolableValue) |
- .sideNumbers(); |
- |
- if (startSideNumbers != endSideNumbers) |
+ .sideTypes(); |
+ if (startSideTypes != endSideTypes) |
return nullptr; |
return PairwiseInterpolationValue(std::move(start.interpolableValue), |
@@ -294,16 +321,16 @@ void CSSBorderImageLengthBoxInterpolationType::composite( |
double underlyingFraction, |
const InterpolationValue& value, |
double interpolationFraction) const { |
- const SideNumbers& underlyingSideNumbers = |
+ const SideTypes& underlyingSideTypes = |
toCSSBorderImageLengthBoxNonInterpolableValue( |
*underlyingValueOwner.value().nonInterpolableValue) |
- .sideNumbers(); |
+ .sideTypes(); |
const auto& nonInterpolableValue = |
toCSSBorderImageLengthBoxNonInterpolableValue( |
*value.nonInterpolableValue); |
- const SideNumbers& sideNumbers = nonInterpolableValue.sideNumbers(); |
+ const SideTypes& sideTypes = nonInterpolableValue.sideTypes(); |
- if (underlyingSideNumbers != sideNumbers) { |
+ if (underlyingSideTypes != sideTypes) { |
underlyingValueOwner.set(*this, value); |
return; |
} |
@@ -320,13 +347,23 @@ void CSSBorderImageLengthBoxInterpolationType::composite( |
nonInterpolableValue.sideNonInterpolableValues(); |
for (size_t i = 0; i < SideIndexCount; i++) { |
- if (sideNumbers.isNumber[i]) |
- underlyingList.getMutable(i)->scaleAndAdd(underlyingFraction, |
- *list.get(i)); |
- else |
- LengthInterpolationFunctions::composite( |
- underlyingList.getMutable(i), underlyingSideNonInterpolableValues[i], |
- underlyingFraction, *list.get(i), sideNonInterpolableValues[i].get()); |
+ switch (sideTypes.type[i]) { |
+ case SideType::Number: |
+ underlyingList.getMutable(i)->scaleAndAdd(underlyingFraction, |
+ *list.get(i)); |
+ break; |
+ case SideType::Length: |
+ LengthInterpolationFunctions::composite( |
+ underlyingList.getMutable(i), |
+ underlyingSideNonInterpolableValues[i], underlyingFraction, |
+ *list.get(i), sideNonInterpolableValues[i].get()); |
+ break; |
+ case SideType::Auto: |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
} |
} |
@@ -334,21 +371,29 @@ void CSSBorderImageLengthBoxInterpolationType::applyStandardPropertyValue( |
const InterpolableValue& interpolableValue, |
const NonInterpolableValue* nonInterpolableValue, |
StyleResolverState& state) const { |
- const SideNumbers& sideNumbers = |
+ const SideTypes& sideTypes = |
toCSSBorderImageLengthBoxNonInterpolableValue(nonInterpolableValue) |
- ->sideNumbers(); |
+ ->sideTypes(); |
const Vector<RefPtr<NonInterpolableValue>>& nonInterpolableValues = |
toCSSBorderImageLengthBoxNonInterpolableValue(nonInterpolableValue) |
->sideNonInterpolableValues(); |
const InterpolableList& list = toInterpolableList(interpolableValue); |
- const auto& convertSide = |
- [&sideNumbers, &list, &state, |
- &nonInterpolableValues](size_t index) -> BorderImageLength { |
- if (sideNumbers.isNumber[index]) |
- return clampTo<double>(toInterpolableNumber(list.get(index))->value(), 0); |
- return LengthInterpolationFunctions::createLength( |
- *list.get(index), nonInterpolableValues[index].get(), |
- state.cssToLengthConversionData(), ValueRangeNonNegative); |
+ const auto& convertSide = [&sideTypes, &list, &state, &nonInterpolableValues]( |
+ size_t index) -> BorderImageLength { |
+ switch (sideTypes.type[index]) { |
+ case SideType::Number: |
+ return clampTo<double>(toInterpolableNumber(list.get(index))->value(), |
+ 0); |
+ case SideType::Auto: |
+ return Length(Auto); |
+ case SideType::Length: |
+ return LengthInterpolationFunctions::createLength( |
+ *list.get(index), nonInterpolableValues[index].get(), |
+ state.cssToLengthConversionData(), ValueRangeNonNegative); |
+ default: |
+ NOTREACHED(); |
+ return Length(Auto); |
+ } |
}; |
BorderImageLengthBox box(convertSide(SideTop), convertSide(SideRight), |
convertSide(SideBottom), convertSide(SideLeft)); |