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/LengthInterpolationFunctions.h" |
| 6 |
| 7 #include "core/css/CSSPrimitiveValue.h" |
| 8 #include "core/css/CSSToLengthConversionData.h" |
| 9 #include "platform/CalculationValue.h" |
| 10 |
| 11 namespace blink { |
| 12 |
| 13 // This class is implemented as a singleton whose instance represents the presen
ce of percentages being used in a Length value |
| 14 // while nullptr represents the absence of any percentages. |
| 15 class CSSLengthNonInterpolableValue : public NonInterpolableValue { |
| 16 public: |
| 17 ~CSSLengthNonInterpolableValue() final { NOTREACHED(); } |
| 18 static PassRefPtr<CSSLengthNonInterpolableValue> create(bool hasPercentage) |
| 19 { |
| 20 DEFINE_STATIC_REF(CSSLengthNonInterpolableValue, singleton, adoptRef(new
CSSLengthNonInterpolableValue())); |
| 21 DCHECK(singleton); |
| 22 return hasPercentage ? singleton : nullptr; |
| 23 } |
| 24 static PassRefPtr<CSSLengthNonInterpolableValue> merge(const NonInterpolable
Value* a, const NonInterpolableValue* b) |
| 25 { |
| 26 return create(hasPercentage(a) || hasPercentage(b)); |
| 27 } |
| 28 static bool hasPercentage(const NonInterpolableValue*); |
| 29 |
| 30 DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
| 31 |
| 32 private: |
| 33 CSSLengthNonInterpolableValue() { } |
| 34 }; |
| 35 |
| 36 DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSLengthNonInterpolableValue); |
| 37 DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSLengthNonInterpolableValue); |
| 38 |
| 39 bool CSSLengthNonInterpolableValue::hasPercentage(const NonInterpolableValue* no
nInterpolableValue) |
| 40 { |
| 41 DCHECK(isCSSLengthNonInterpolableValue(nonInterpolableValue)); |
| 42 return static_cast<bool>(nonInterpolableValue); |
| 43 } |
| 44 |
| 45 std::unique_ptr<InterpolableValue> LengthInterpolationFunctions::createInterpola
blePixels(double pixels) |
| 46 { |
| 47 std::unique_ptr<InterpolableList> interpolableList = createNeutralInterpolab
leValue(); |
| 48 interpolableList->set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber:
:create(pixels)); |
| 49 return std::move(interpolableList); |
| 50 } |
| 51 |
| 52 InterpolationValue LengthInterpolationFunctions::createInterpolablePercent(doubl
e percent) |
| 53 { |
| 54 std::unique_ptr<InterpolableList> interpolableList = createNeutralInterpolab
leValue(); |
| 55 interpolableList->set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNum
ber::create(percent)); |
| 56 return InterpolationValue(std::move(interpolableList), CSSLengthNonInterpola
bleValue::create(true)); |
| 57 } |
| 58 |
| 59 std::unique_ptr<InterpolableList> LengthInterpolationFunctions::createNeutralInt
erpolableValue() |
| 60 { |
| 61 const size_t length = CSSPrimitiveValue::LengthUnitTypeCount; |
| 62 std::unique_ptr<InterpolableList> values = InterpolableList::create(length); |
| 63 for (size_t i = 0; i < length; i++) |
| 64 values->set(i, InterpolableNumber::create(0)); |
| 65 return values; |
| 66 } |
| 67 |
| 68 InterpolationValue LengthInterpolationFunctions::maybeConvertCSSValue(const CSSV
alue& value) |
| 69 { |
| 70 if (!value.isPrimitiveValue()) |
| 71 return nullptr; |
| 72 |
| 73 const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value); |
| 74 if (!primitiveValue.isLength() && !primitiveValue.isPercentage() && !primiti
veValue.isCalculatedPercentageWithLength()) |
| 75 return nullptr; |
| 76 |
| 77 CSSLengthArray lengthArray; |
| 78 primitiveValue.accumulateLengthArray(lengthArray); |
| 79 |
| 80 std::unique_ptr<InterpolableList> values = InterpolableList::create(CSSPrimi
tiveValue::LengthUnitTypeCount); |
| 81 for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) |
| 82 values->set(i, InterpolableNumber::create(lengthArray.values[i])); |
| 83 |
| 84 bool hasPercentage = lengthArray.typeFlags.get(CSSPrimitiveValue::UnitTypePe
rcentage); |
| 85 return InterpolationValue(std::move(values), CSSLengthNonInterpolableValue::
create(hasPercentage)); |
| 86 } |
| 87 |
| 88 InterpolationValue LengthInterpolationFunctions::maybeConvertLength(const Length
& length, float zoom) |
| 89 { |
| 90 if (!length.isSpecified()) |
| 91 return nullptr; |
| 92 |
| 93 PixelsAndPercent pixelsAndPercent = length.getPixelsAndPercent(); |
| 94 std::unique_ptr<InterpolableList> values = createNeutralInterpolableValue(); |
| 95 values->set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pi
xelsAndPercent.pixels / zoom)); |
| 96 values->set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::creat
e(pixelsAndPercent.percent)); |
| 97 |
| 98 return InterpolationValue(std::move(values), CSSLengthNonInterpolableValue::
create(length.isPercentOrCalc())); |
| 99 } |
| 100 |
| 101 PairwiseInterpolationValue LengthInterpolationFunctions::mergeSingles(Interpolat
ionValue&& start, InterpolationValue&& end) |
| 102 { |
| 103 return PairwiseInterpolationValue( |
| 104 std::move(start.interpolableValue), |
| 105 std::move(end.interpolableValue), |
| 106 CSSLengthNonInterpolableValue::merge(start.nonInterpolableValue.get(), e
nd.nonInterpolableValue.get())); |
| 107 } |
| 108 |
| 109 bool LengthInterpolationFunctions::nonInterpolableValuesAreCompatible(const NonI
nterpolableValue* a, const NonInterpolableValue* b) |
| 110 { |
| 111 DCHECK(isCSSLengthNonInterpolableValue(a)); |
| 112 DCHECK(isCSSLengthNonInterpolableValue(b)); |
| 113 return true; |
| 114 } |
| 115 |
| 116 void LengthInterpolationFunctions::composite( |
| 117 std::unique_ptr<InterpolableValue>& underlyingInterpolableValue, |
| 118 RefPtr<NonInterpolableValue>& underlyingNonInterpolableValue, |
| 119 double underlyingFraction, |
| 120 const InterpolableValue& interpolableValue, |
| 121 const NonInterpolableValue* nonInterpolableValue) |
| 122 { |
| 123 underlyingInterpolableValue->scaleAndAdd(underlyingFraction, interpolableVal
ue); |
| 124 underlyingNonInterpolableValue = CSSLengthNonInterpolableValue::merge(underl
yingNonInterpolableValue.get(), nonInterpolableValue); |
| 125 } |
| 126 |
| 127 void LengthInterpolationFunctions::subtractFromOneHundredPercent(InterpolationVa
lue& result) |
| 128 { |
| 129 InterpolableList& list = toInterpolableList(*result.interpolableValue); |
| 130 for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| 131 double value = -toInterpolableNumber(*list.get(i)).value(); |
| 132 if (i == CSSPrimitiveValue::UnitTypePercentage) |
| 133 value += 100; |
| 134 toInterpolableNumber(*list.getMutable(i)).set(value); |
| 135 } |
| 136 result.nonInterpolableValue = CSSLengthNonInterpolableValue::create(true); |
| 137 } |
| 138 |
| 139 static double clampToRange(double x, ValueRange range) |
| 140 { |
| 141 return (range == ValueRangeNonNegative && x < 0) ? 0 : x; |
| 142 } |
| 143 |
| 144 Length LengthInterpolationFunctions::createLength(const InterpolableValue& inter
polableValue, const NonInterpolableValue* nonInterpolableValue, const CSSToLengt
hConversionData& conversionData, ValueRange range) |
| 145 { |
| 146 const InterpolableList& interpolableList = toInterpolableList(interpolableVa
lue); |
| 147 bool hasPercentage = CSSLengthNonInterpolableValue::hasPercentage(nonInterpo
lableValue); |
| 148 double pixels = 0; |
| 149 double percentage = 0; |
| 150 for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| 151 double value = toInterpolableNumber(*interpolableList.get(i)).value(); |
| 152 if (i == CSSPrimitiveValue::UnitTypePercentage) { |
| 153 percentage = value; |
| 154 } else { |
| 155 CSSPrimitiveValue::UnitType type = CSSPrimitiveValue::lengthUnitType
ToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(i)); |
| 156 pixels += conversionData.zoomedComputedPixels(value, type); |
| 157 } |
| 158 } |
| 159 |
| 160 if (percentage != 0) |
| 161 hasPercentage = true; |
| 162 if (pixels != 0 && hasPercentage) |
| 163 return Length(CalculationValue::create(PixelsAndPercent(pixels, percenta
ge), range)); |
| 164 if (hasPercentage) |
| 165 return Length(clampToRange(percentage, range), Percent); |
| 166 return Length(CSSPrimitiveValue::clampToCSSLengthRange(clampToRange(pixels,
range)), Fixed); |
| 167 } |
| 168 |
| 169 } // namespace blink |
OLD | NEW |