OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/animation/CSSSizeListInterpolationType.h" |
| 6 |
| 7 #include "core/animation/ListInterpolationFunctions.h" |
| 8 #include "core/animation/SizeInterpolationFunctions.h" |
| 9 #include "core/animation/SizeListPropertyFunctions.h" |
| 10 #include "core/css/CSSValueList.h" |
| 11 #include "core/css/resolver/StyleResolverState.h" |
| 12 |
| 13 namespace blink { |
| 14 |
| 15 class UnderlyingSizeListChecker : public InterpolationType::ConversionChecker { |
| 16 public: |
| 17 ~UnderlyingSizeListChecker() final {} |
| 18 |
| 19 static std::unique_ptr<UnderlyingSizeListChecker> create(const NonInterpolab
leList& underlyingList) |
| 20 { |
| 21 return wrapUnique(new UnderlyingSizeListChecker(underlyingList)); |
| 22 } |
| 23 |
| 24 private: |
| 25 UnderlyingSizeListChecker(const NonInterpolableList& underlyingList) |
| 26 : m_underlyingList(&underlyingList) |
| 27 { } |
| 28 |
| 29 bool isValid(const InterpolationEnvironment&, const InterpolationValue& unde
rlying) const final |
| 30 { |
| 31 const auto& underlyingList = toNonInterpolableList(*underlying.nonInterp
olableValue); |
| 32 size_t underlyingLength = underlyingList.length(); |
| 33 if (underlyingLength != m_underlyingList->length()) |
| 34 return false; |
| 35 for (size_t i = 0; i < underlyingLength; i++) { |
| 36 bool compatible = SizeInterpolationFunctions::nonInterpolableValuesA
reCompatible( |
| 37 underlyingList.get(i), m_underlyingList->get(i)); |
| 38 if (!compatible) |
| 39 return false; |
| 40 } |
| 41 return true; |
| 42 } |
| 43 |
| 44 RefPtr<const NonInterpolableList> m_underlyingList; |
| 45 }; |
| 46 |
| 47 class InheritedSizeListChecker : public InterpolationType::ConversionChecker { |
| 48 public: |
| 49 ~InheritedSizeListChecker() final {} |
| 50 |
| 51 static std::unique_ptr<InheritedSizeListChecker> create(CSSPropertyID proper
ty, const SizeList& inheritedSizeList) |
| 52 { |
| 53 return wrapUnique(new InheritedSizeListChecker(property, inheritedSizeLi
st)); |
| 54 } |
| 55 |
| 56 private: |
| 57 InheritedSizeListChecker(CSSPropertyID property, const SizeList& inheritedSi
zeList) |
| 58 : m_property(property) |
| 59 , m_inheritedSizeList(inheritedSizeList) |
| 60 { } |
| 61 |
| 62 bool isValid(const InterpolationEnvironment& environment, const Interpolatio
nValue&) const final |
| 63 { |
| 64 return m_inheritedSizeList == SizeListPropertyFunctions::getSizeList(m_p
roperty, *environment.state().parentStyle()); |
| 65 } |
| 66 |
| 67 CSSPropertyID m_property; |
| 68 SizeList m_inheritedSizeList; |
| 69 }; |
| 70 |
| 71 InterpolationValue convertSizeList(const SizeList& sizeList, float zoom) |
| 72 { |
| 73 // Flatten pairs of width/height into individual items, even for contain and
cover keywords. |
| 74 return ListInterpolationFunctions::createList(sizeList.size() * 2, [&sizeLis
t, zoom](size_t index) -> InterpolationValue { |
| 75 bool convertWidth = index % 2 == 0; |
| 76 return SizeInterpolationFunctions::convertFillSizeSide(sizeList[index /
2], zoom, convertWidth); |
| 77 }); |
| 78 } |
| 79 |
| 80 InterpolationValue maybeConvertCSSSizeList(const CSSValue& value) |
| 81 { |
| 82 // CSSPropertyParser doesn't put single values in lists so wrap it up in a t
emporary list. |
| 83 const CSSValueList* list = nullptr; |
| 84 if (!value.isBaseValueList()) { |
| 85 CSSValueList* tempList = CSSValueList::createCommaSeparated(); |
| 86 tempList->append(value); |
| 87 list = tempList; |
| 88 } else { |
| 89 list = toCSSValueList(&value); |
| 90 } |
| 91 |
| 92 // Flatten pairs of width/height into individual items, even for contain and
cover keywords. |
| 93 return ListInterpolationFunctions::createList(list->length() * 2, [list](siz
e_t index) -> InterpolationValue { |
| 94 const CSSValue& cssSize = list->item(index / 2); |
| 95 bool convertWidth = index % 2 == 0; |
| 96 return SizeInterpolationFunctions::maybeConvertCSSSizeSide(cssSize, conv
ertWidth); |
| 97 }); |
| 98 } |
| 99 |
| 100 InterpolationValue CSSSizeListInterpolationType::maybeConvertNeutral(const Inter
polationValue& underlying, ConversionCheckers& conversionCheckers) const |
| 101 { |
| 102 const auto& underlyingList = toNonInterpolableList(*underlying.nonInterpolab
leValue); |
| 103 conversionCheckers.append(UnderlyingSizeListChecker::create(underlyingList))
; |
| 104 return ListInterpolationFunctions::createList(underlyingList.length(), [&und
erlyingList](size_t index) { |
| 105 return SizeInterpolationFunctions::createNeutralValue(underlyingList.get
(index)); |
| 106 }); |
| 107 } |
| 108 |
| 109 InterpolationValue CSSSizeListInterpolationType::maybeConvertInitial(const Style
ResolverState&, ConversionCheckers&) const |
| 110 { |
| 111 return convertSizeList(SizeListPropertyFunctions::getInitialSizeList(cssProp
erty()), 1); |
| 112 } |
| 113 |
| 114 InterpolationValue CSSSizeListInterpolationType::maybeConvertInherit(const Style
ResolverState& state, ConversionCheckers& conversionCheckers) const |
| 115 { |
| 116 SizeList inheritedSizeList = SizeListPropertyFunctions::getSizeList(cssPrope
rty(), *state.parentStyle()); |
| 117 conversionCheckers.append(InheritedSizeListChecker::create(cssProperty(), in
heritedSizeList)); |
| 118 return convertSizeList(inheritedSizeList, state.style()->effectiveZoom()); |
| 119 } |
| 120 |
| 121 InterpolationValue CSSSizeListInterpolationType::maybeConvertValue(const CSSValu
e& value, const StyleResolverState&, ConversionCheckers&) const |
| 122 { |
| 123 return maybeConvertCSSSizeList(value); |
| 124 } |
| 125 |
| 126 PairwiseInterpolationValue CSSSizeListInterpolationType::maybeMergeSingles(Inter
polationValue&& start, InterpolationValue&& end) const |
| 127 { |
| 128 return ListInterpolationFunctions::maybeMergeSingles(std::move(start), std::
move(end), SizeInterpolationFunctions::maybeMergeSingles); |
| 129 } |
| 130 |
| 131 InterpolationValue CSSSizeListInterpolationType::maybeConvertUnderlyingValue(con
st InterpolationEnvironment& environment) const |
| 132 { |
| 133 const ComputedStyle& style = *environment.state().style(); |
| 134 return convertSizeList(SizeListPropertyFunctions::getSizeList(cssProperty(),
style), style.effectiveZoom()); |
| 135 } |
| 136 |
| 137 void CSSSizeListInterpolationType::composite(UnderlyingValueOwner& underlyingVal
ueOwner, double underlyingFraction, const InterpolationValue& value, double inte
rpolationFraction) const |
| 138 { |
| 139 ListInterpolationFunctions::composite(underlyingValueOwner, underlyingFracti
on, *this, value, |
| 140 SizeInterpolationFunctions::nonInterpolableValuesAreCompatible, |
| 141 SizeInterpolationFunctions::composite); |
| 142 } |
| 143 |
| 144 void CSSSizeListInterpolationType::apply(const InterpolableValue& interpolableVa
lue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment&
environment) const |
| 145 { |
| 146 const auto& interpolableList = toInterpolableList(interpolableValue); |
| 147 const auto& nonInterpolableList = toNonInterpolableList(*nonInterpolableValu
e); |
| 148 size_t length = interpolableList.length(); |
| 149 DCHECK_EQ(length, nonInterpolableList.length()); |
| 150 DCHECK_EQ(length % 2, 0ul); |
| 151 size_t sizeListLength = length / 2; |
| 152 SizeList sizeList(sizeListLength); |
| 153 for (size_t i = 0; i < sizeListLength; i++) { |
| 154 sizeList[i] = SizeInterpolationFunctions::createFillSize( |
| 155 *interpolableList.get(i * 2), |
| 156 nonInterpolableList.get(i * 2), |
| 157 *interpolableList.get(i * 2 + 1), |
| 158 nonInterpolableList.get(i * 2 + 1), |
| 159 environment.state().cssToLengthConversionData()); |
| 160 } |
| 161 SizeListPropertyFunctions::setSizeList(cssProperty(), *environment.state().s
tyle(), sizeList); |
| 162 } |
| 163 |
| 164 } // namespace blink |
OLD | NEW |