1 // Copyright 2014 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.
6 #include "core/animation/DoubleStyleInterpolation.h"
8 #include "core/css/CSSValueList.h"
9 #include "core/css/resolver/StyleBuilder.h"
10 #include "core/style/ComputedStyleConstants.h"
14 bool DoubleStyleInterpolation::canCreateFrom(const CSSValue
& value
)
16 return value
.isPrimitiveValue() && (toCSSPrimitiveValue(value
).isNumber() || toCSSPrimitiveValue(value
).isAngle());
19 PassOwnPtr
<InterpolableValue
> DoubleStyleInterpolation::doubleToInterpolableValue(const CSSValue
& value
)
21 ASSERT(canCreateFrom(value
));
22 const CSSPrimitiveValue
& primitive
= toCSSPrimitiveValue(value
);
23 if (primitive
.isNumber())
24 return InterpolableNumber::create(primitive
.getDoubleValue());
25 if (primitive
.isAngle())
26 return InterpolableNumber::create(primitive
.computeDegrees());
31 static double clampToRange(double value
, InterpolationRange clamp
)
38 return clampTo
<float>(value
, 0, 1);
39 case RangeOpacityFIXME
:
40 return clampTo
<float>(value
, 0, nextafterf(1, 0));
45 case RangeRoundGreaterThanOrEqualToOne
:
46 return clampTo
<float>(round(value
), 1);
47 case RangeGreaterThanOrEqualToOne
:
48 return clampTo
<float>(value
, 1);
49 case RangeNonNegative
:
50 return clampTo
<float>(value
, 0);
57 PassRefPtrWillBeRawPtr
<CSSValue
> DoubleStyleInterpolation::interpolableValueToDouble(const InterpolableValue
* value
, bool isNumber
, InterpolationRange clamp
)
59 ASSERT(value
->isNumber());
60 double doubleValue
= clampToRange(toInterpolableNumber(value
)->value(), clamp
);
63 return CSSPrimitiveValue::create(doubleValue
, CSSPrimitiveValue::UnitType::Number
);
64 return CSSPrimitiveValue::create(doubleValue
, CSSPrimitiveValue::UnitType::Degrees
);
67 void DoubleStyleInterpolation::apply(StyleResolverState
& state
) const
69 if (m_id
!= CSSPropertyMotionRotation
) {
70 StyleBuilder::applyProperty(m_id
, state
, interpolableValueToDouble(m_cachedValue
.get(), m_isNumber
, m_clamp
).get());
74 StyleBuilder::applyProperty(m_id
, state
, interpolableValueToMotionRotation(m_cachedValue
.get(), m_flag
).get());
77 PassOwnPtr
<InterpolableValue
> DoubleStyleInterpolation::toInterpolableValue(const CSSValue
& value
, CSSPropertyID property
)
79 ASSERT(canCreateFrom(value
));
80 return doubleToInterpolableValue(value
);
83 PassRefPtrWillBeRawPtr
<CSSValue
> DoubleStyleInterpolation::fromInterpolableValue(const InterpolableValue
& value
, InterpolationRange range
)
85 return interpolableValueToDouble(&value
, true, range
);
90 bool extractMotionRotation(const CSSValue
& value
, float* rotation
, MotionRotationType
* rotationType
)
93 *rotationType
= MotionRotationFixed
;
95 if (!value
.isValueList())
97 const CSSValueList
& list
= toCSSValueList(value
);
99 int len
= list
.length();
100 for (int i
= 0; i
< len
; i
++) {
101 const CSSValue
* item
= list
.item(i
);
102 if (!item
->isPrimitiveValue())
104 const CSSPrimitiveValue
* primitiveValue
= toCSSPrimitiveValue(item
);
105 if (primitiveValue
->getValueID() == CSSValueAuto
) {
106 *rotationType
= MotionRotationAuto
;
107 } else if (primitiveValue
->getValueID() == CSSValueReverse
) {
108 *rotationType
= MotionRotationAuto
;
110 } else if (primitiveValue
->isAngle()) {
111 *rotation
+= primitiveValue
->computeDegrees();
121 PassRefPtrWillBeRawPtr
<CSSValue
> DoubleStyleInterpolation::interpolableValueToMotionRotation(InterpolableValue
* value
, bool flag
)
123 RefPtrWillBeRawPtr
<CSSValueList
> list
= CSSValueList::createSpaceSeparated();
125 list
->append(CSSPrimitiveValue::createIdentifier(CSSValueAuto
));
126 ASSERT(value
->isNumber());
127 list
->append(CSSPrimitiveValue::create(toInterpolableNumber(value
)->value(), CSSPrimitiveValue::UnitType::Degrees
));
128 return list
.release();
131 PassOwnPtr
<InterpolableValue
> DoubleStyleInterpolation::motionRotationToInterpolableValue(const CSSValue
& value
)
134 MotionRotationType rotationType
;
135 extractMotionRotation(value
, &rotation
, &rotationType
);
137 return InterpolableNumber::create(rotation
);
140 PassRefPtr
<DoubleStyleInterpolation
> DoubleStyleInterpolation::maybeCreateFromMotionRotation(const CSSValue
& start
, const CSSValue
& end
, CSSPropertyID id
)
142 float startRotation
, endRotation
;
143 MotionRotationType startRotationType
, endRotationType
;
145 if (!extractMotionRotation(start
, &startRotation
, &startRotationType
)
146 || !extractMotionRotation(end
, &endRotation
, &endRotationType
)
147 || startRotationType
!= endRotationType
)
150 return adoptRef(new DoubleStyleInterpolation(
151 motionRotationToInterpolableValue(start
),
152 motionRotationToInterpolableValue(end
),
153 id
, true, InterpolationRange::RangeAll
, startRotationType
== MotionRotationAuto
));