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/SizeInterpolationFunctions.h" |
| 6 |
| 7 #include "core/animation/LengthInterpolationFunctions.h" |
| 8 #include "core/animation/UnderlyingValueOwner.h" |
| 9 #include "core/css/CSSToLengthConversionData.h" |
| 10 #include "core/css/CSSValuePair.h" |
| 11 |
| 12 namespace blink { |
| 13 |
| 14 class CSSSizeNonInterpolableValue : public NonInterpolableValue { |
| 15 public: |
| 16 static PassRefPtr<CSSSizeNonInterpolableValue> create(CSSValueID keyword) |
| 17 { |
| 18 return adoptRef(new CSSSizeNonInterpolableValue(keyword)); |
| 19 } |
| 20 |
| 21 static PassRefPtr<CSSSizeNonInterpolableValue> create(PassRefPtr<NonInterpol
ableValue> lengthNonInterpolableValue) |
| 22 { |
| 23 return adoptRef(new CSSSizeNonInterpolableValue(lengthNonInterpolableVal
ue)); |
| 24 } |
| 25 |
| 26 bool isKeyword() const { return m_keyword != CSSValueInvalid; } |
| 27 CSSValueID keyword() const { DCHECK(isKeyword()); return m_keyword; } |
| 28 |
| 29 const NonInterpolableValue* lengthNonInterpolableValue() const { DCHECK(!isK
eyword()); return m_lengthNonInterpolableValue.get(); } |
| 30 RefPtr<NonInterpolableValue>& lengthNonInterpolableValue() { DCHECK(!isKeywo
rd()); return m_lengthNonInterpolableValue; } |
| 31 |
| 32 DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
| 33 |
| 34 private: |
| 35 CSSSizeNonInterpolableValue(CSSValueID keyword) |
| 36 : m_keyword(keyword) |
| 37 , m_lengthNonInterpolableValue(nullptr) |
| 38 { |
| 39 DCHECK_NE(keyword, CSSValueInvalid); |
| 40 } |
| 41 |
| 42 CSSSizeNonInterpolableValue(PassRefPtr<NonInterpolableValue> lengthNonInterp
olableValue) |
| 43 : m_keyword(CSSValueInvalid) |
| 44 , m_lengthNonInterpolableValue(lengthNonInterpolableValue) |
| 45 { } |
| 46 |
| 47 CSSValueID m_keyword; |
| 48 RefPtr<NonInterpolableValue> m_lengthNonInterpolableValue; |
| 49 }; |
| 50 |
| 51 DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSSizeNonInterpolableValue); |
| 52 DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSSizeNonInterpolableValue); |
| 53 |
| 54 static InterpolationValue convertKeyword(CSSValueID keyword) |
| 55 { |
| 56 return InterpolationValue(InterpolableList::create(0), CSSSizeNonInterpolabl
eValue::create(keyword)); |
| 57 } |
| 58 |
| 59 static InterpolationValue wrapConvertedLength(InterpolationValue&& convertedLeng
th) |
| 60 { |
| 61 if (!convertedLength) |
| 62 return nullptr; |
| 63 return InterpolationValue( |
| 64 std::move(convertedLength.interpolableValue), |
| 65 CSSSizeNonInterpolableValue::create(convertedLength.nonInterpolableValue
.release())); |
| 66 } |
| 67 |
| 68 InterpolationValue SizeInterpolationFunctions::convertFillSizeSide(const FillSiz
e& fillSize, float zoom, bool convertWidth) |
| 69 { |
| 70 switch (fillSize.type) { |
| 71 case SizeLength: { |
| 72 const Length& side = convertWidth ? fillSize.size.width() : fillSize.siz
e.height(); |
| 73 if (side.isAuto()) |
| 74 return convertKeyword(CSSValueAuto); |
| 75 return wrapConvertedLength(LengthInterpolationFunctions::maybeConvertLen
gth(side, zoom)); |
| 76 } |
| 77 case Contain: |
| 78 return convertKeyword(CSSValueContain); |
| 79 case Cover: |
| 80 return convertKeyword(CSSValueCover); |
| 81 case SizeNone: |
| 82 default: |
| 83 NOTREACHED(); |
| 84 return nullptr; |
| 85 } |
| 86 } |
| 87 |
| 88 InterpolationValue SizeInterpolationFunctions::maybeConvertCSSSizeSide(const CSS
Value& value, bool convertWidth) |
| 89 { |
| 90 if (value.isValuePair()) { |
| 91 const CSSValuePair& pair = toCSSValuePair(value); |
| 92 const CSSValue& side = convertWidth ? pair.first() : pair.second(); |
| 93 if (side.isPrimitiveValue() && toCSSPrimitiveValue(side).getValueID() ==
CSSValueAuto) |
| 94 return convertKeyword(CSSValueAuto); |
| 95 return wrapConvertedLength(LengthInterpolationFunctions::maybeConvertCSS
Value(side)); |
| 96 } |
| 97 |
| 98 if (!value.isPrimitiveValue()) |
| 99 return nullptr; |
| 100 CSSValueID keyword = toCSSPrimitiveValue(value).getValueID(); |
| 101 if (keyword) |
| 102 return convertKeyword(keyword); |
| 103 |
| 104 // A single length is equivalent to "<length> auto". |
| 105 if (convertWidth) |
| 106 return wrapConvertedLength(LengthInterpolationFunctions::maybeConvertCSS
Value(value)); |
| 107 return convertKeyword(CSSValueAuto); |
| 108 } |
| 109 |
| 110 PairwiseInterpolationValue SizeInterpolationFunctions::maybeMergeSingles(Interpo
lationValue&& start, InterpolationValue&& end) |
| 111 { |
| 112 if (!nonInterpolableValuesAreCompatible(start.nonInterpolableValue.get(), en
d.nonInterpolableValue.get())) |
| 113 return nullptr; |
| 114 return PairwiseInterpolationValue( |
| 115 std::move(start.interpolableValue), |
| 116 std::move(end.interpolableValue), |
| 117 start.nonInterpolableValue.release()); |
| 118 } |
| 119 |
| 120 InterpolationValue SizeInterpolationFunctions::createNeutralValue(const NonInter
polableValue* nonInterpolableValue) |
| 121 { |
| 122 auto& size = toCSSSizeNonInterpolableValue(*nonInterpolableValue); |
| 123 if (size.isKeyword()) |
| 124 return convertKeyword(size.keyword()); |
| 125 return wrapConvertedLength(InterpolationValue(LengthInterpolationFunctions::
createNeutralInterpolableValue())); |
| 126 } |
| 127 |
| 128 bool SizeInterpolationFunctions::nonInterpolableValuesAreCompatible(const NonInt
erpolableValue* a, const NonInterpolableValue* b) |
| 129 { |
| 130 const auto& sizeA = toCSSSizeNonInterpolableValue(*a); |
| 131 const auto& sizeB = toCSSSizeNonInterpolableValue(*b); |
| 132 if (sizeA.isKeyword() != sizeB.isKeyword()) |
| 133 return false; |
| 134 if (sizeA.isKeyword()) |
| 135 return sizeA.keyword() == sizeB.keyword(); |
| 136 return true; |
| 137 } |
| 138 |
| 139 void SizeInterpolationFunctions::composite(std::unique_ptr<InterpolableValue>& u
nderlyingInterpolableValue, RefPtr<NonInterpolableValue>& underlyingNonInterpola
bleValue, double underlyingFraction, const InterpolableValue& interpolableValue,
const NonInterpolableValue* nonInterpolableValue) |
| 140 { |
| 141 const auto& sizeNonInterpolableValue = toCSSSizeNonInterpolableValue(*nonInt
erpolableValue); |
| 142 if (sizeNonInterpolableValue.isKeyword()) |
| 143 return; |
| 144 auto& underlyingSizeNonInterpolableValue = toCSSSizeNonInterpolableValue(*un
derlyingNonInterpolableValue); |
| 145 LengthInterpolationFunctions::composite( |
| 146 underlyingInterpolableValue, |
| 147 underlyingSizeNonInterpolableValue.lengthNonInterpolableValue(), |
| 148 underlyingFraction, |
| 149 interpolableValue, |
| 150 sizeNonInterpolableValue.lengthNonInterpolableValue()); |
| 151 } |
| 152 |
| 153 static Length createLength(const InterpolableValue& interpolableValue, const CSS
SizeNonInterpolableValue& nonInterpolableValue, const CSSToLengthConversionData&
conversionData) |
| 154 { |
| 155 if (nonInterpolableValue.isKeyword()) { |
| 156 DCHECK_EQ(nonInterpolableValue.keyword(), CSSValueAuto); |
| 157 return Length(Auto); |
| 158 } |
| 159 return LengthInterpolationFunctions::createLength(interpolableValue, nonInte
rpolableValue.lengthNonInterpolableValue(), conversionData, ValueRangeNonNegativ
e); |
| 160 } |
| 161 |
| 162 FillSize SizeInterpolationFunctions::createFillSize(const InterpolableValue& int
erpolableValueA, const NonInterpolableValue* nonInterpolableValueA, const Interp
olableValue& interpolableValueB, const NonInterpolableValue* nonInterpolableValu
eB, const CSSToLengthConversionData& conversionData) |
| 163 { |
| 164 const auto& sideA = toCSSSizeNonInterpolableValue(*nonInterpolableValueA); |
| 165 const auto& sideB = toCSSSizeNonInterpolableValue(*nonInterpolableValueB); |
| 166 if (sideA.isKeyword()) { |
| 167 switch (sideA.keyword()) { |
| 168 case CSSValueCover: |
| 169 DCHECK_EQ(sideA.keyword(), sideB.keyword()); |
| 170 return FillSize(Cover, LengthSize()); |
| 171 case CSSValueContain: |
| 172 DCHECK_EQ(sideA.keyword(), sideB.keyword()); |
| 173 return FillSize(Contain, LengthSize()); |
| 174 case CSSValueAuto: |
| 175 break; |
| 176 default: |
| 177 NOTREACHED(); |
| 178 break; |
| 179 } |
| 180 } |
| 181 return FillSize(SizeLength, LengthSize( |
| 182 createLength(interpolableValueA, sideA, conversionData), |
| 183 createLength(interpolableValueB, sideB, conversionData))); |
| 184 } |
| 185 |
| 186 } // namespace blink |
OLD | NEW |