OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "core/animation/AnimatableNumber.h" | |
33 | |
34 #include "core/css/CSSPrimitiveValueMappings.h" | |
35 #include "core/platform/CalculationValue.h" | |
36 #include "core/platform/Length.h" | |
37 #include "wtf/MathExtras.h" | |
38 | |
39 namespace WebCore { | |
40 | |
41 PassRefPtr<AnimatableNumber> AnimatableNumber::create(CSSValue* value) | |
42 { | |
43 ASSERT(canCreateFrom(value)); | |
44 if (value->isPrimitiveValue()) { | |
45 CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(value); | |
46 const CSSCalcValue* calcValue = primitiveValue->cssCalcValue(); | |
47 if (calcValue) | |
48 return create(calcValue->expressionNode(), primitiveValue); | |
49 NumberUnitType unitType = primitiveUnitToNumberType(primitiveValue->prim
itiveType()); | |
50 ASSERT(unitType != UnitTypeInvalid); | |
51 const double scale = CSSPrimitiveValue::conversionToCanonicalUnitsScaleF
actor(primitiveValue->primitiveType()); | |
52 return create(primitiveValue->getDoubleValue() * scale, unitType, primit
iveValue); | |
53 } | |
54 | |
55 if (value->isCalcValue()) | |
56 return create(toCSSCalcValue(value)->expressionNode()); | |
57 | |
58 ASSERT_NOT_REACHED(); | |
59 return 0; | |
60 } | |
61 | |
62 PassRefPtr<AnimatableNumber> AnimatableNumber::create(const AnimatableNumber* le
ftAddend, const AnimatableNumber* rightAddend) | |
63 { | |
64 ASSERT(leftAddend); | |
65 ASSERT(rightAddend); | |
66 | |
67 if (!leftAddend->m_isCalc && !rightAddend->m_isCalc && leftAddend->m_unitTyp
e == rightAddend->m_unitType) | |
68 return create(leftAddend->m_number + rightAddend->m_number, leftAddend->
m_unitType); | |
69 return create(CSSCalcValue::createExpressionNode(leftAddend->toCSSCalcExpres
sionNode(), rightAddend->toCSSCalcExpressionNode(), CalcAdd)); | |
70 } | |
71 | |
72 bool AnimatableNumber::canCreateFrom(const CSSValue* value) | |
73 { | |
74 ASSERT(value); | |
75 if (value->isPrimitiveValue()) { | |
76 const CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(v
alue); | |
77 if (primitiveValue->cssCalcValue()) | |
78 return true; | |
79 return primitiveUnitToNumberType(primitiveValue->primitiveType()) != Uni
tTypeInvalid; | |
80 } | |
81 return value->isCalcValue(); | |
82 } | |
83 | |
84 PassRefPtr<CSSValue> AnimatableNumber::toCSSValue(NumberRange range) const | |
85 { | |
86 return toCSSPrimitiveValue(range); | |
87 } | |
88 | |
89 double AnimatableNumber::toDouble() const | |
90 { | |
91 ASSERT(m_unitType == UnitTypeNumber); | |
92 return m_number; | |
93 } | |
94 | |
95 Length AnimatableNumber::toLength(const RenderStyle* style, const RenderStyle* r
ootStyle, double zoom, NumberRange range) const | |
96 { | |
97 if (!m_isCalc) { | |
98 // Avoid creating a CSSValue in the common cases | |
99 if (m_unitType == UnitTypeLength) | |
100 return Length(clampedNumber(range) * zoom, Fixed); | |
101 if (m_unitType == UnitTypePercentage) | |
102 return Length(clampedNumber(range), Percent); | |
103 } | |
104 return toCSSPrimitiveValue(range)->convertToLength<AnyConversion>(style, roo
tStyle, zoom); | |
105 } | |
106 | |
107 PassRefPtr<AnimatableValue> AnimatableNumber::interpolateTo(const AnimatableValu
e* value, double fraction) const | |
108 { | |
109 const AnimatableNumber* number = toAnimatableNumber(value); | |
110 return AnimatableNumber::create(scale(1 - fraction).get(), number->scale(fra
ction).get()); | |
111 } | |
112 | |
113 PassRefPtr<AnimatableValue> AnimatableNumber::addWith(const AnimatableValue* val
ue) const | |
114 { | |
115 // Optimization for adding with 0. | |
116 if (!m_isCalc && !m_number) | |
117 return takeConstRef(value); | |
118 const AnimatableNumber* number = toAnimatableNumber(value); | |
119 if (!number->m_isCalc && !number->m_number) | |
120 return takeConstRef(this); | |
121 | |
122 return AnimatableNumber::create(this, number); | |
123 } | |
124 | |
125 PassRefPtr<CSSCalcExpressionNode> AnimatableNumber::toCSSCalcExpressionNode() co
nst | |
126 { | |
127 if (m_isCalc) | |
128 return m_calcExpression; | |
129 return CSSCalcValue::createExpressionNode(toCSSPrimitiveValue(AllValues), m_
number == trunc(m_number)); | |
130 } | |
131 | |
132 static bool isCompatibleWithRange(const CSSPrimitiveValue* primitiveValue, Numbe
rRange range) | |
133 { | |
134 ASSERT(primitiveValue); | |
135 if (range == AllValues) | |
136 return true; | |
137 if (primitiveValue->isCalculated()) | |
138 return primitiveValue->cssCalcValue()->permittedValueRange() == Calculat
ionRangeNonNegative; | |
139 return primitiveValue->getDoubleValue() >= 0; | |
140 } | |
141 | |
142 PassRefPtr<CSSPrimitiveValue> AnimatableNumber::toCSSPrimitiveValue(NumberRange
range) const | |
143 { | |
144 ASSERT(m_unitType != UnitTypeInvalid); | |
145 if (!m_cachedCSSPrimitiveValue || !isCompatibleWithRange(m_cachedCSSPrimitiv
eValue.get(), range)) { | |
146 if (m_isCalc) | |
147 m_cachedCSSPrimitiveValue = CSSPrimitiveValue::create(CSSCalcValue::
create(m_calcExpression, range == AllValues ? CalculationRangeAll : CalculationR
angeNonNegative)); | |
148 else | |
149 m_cachedCSSPrimitiveValue = CSSPrimitiveValue::create(clampedNumber(
range), static_cast<CSSPrimitiveValue::UnitTypes>(numberTypeToPrimitiveUnit(m_un
itType))); | |
150 } | |
151 return m_cachedCSSPrimitiveValue; | |
152 } | |
153 | |
154 PassRefPtr<AnimatableNumber> AnimatableNumber::scale(double factor) const | |
155 { | |
156 if (m_isCalc) { | |
157 return AnimatableNumber::create(CSSCalcValue::createExpressionNode( | |
158 m_calcExpression, | |
159 CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(factor,
CSSPrimitiveValue::CSS_NUMBER)), | |
160 CalcMultiply)); | |
161 } | |
162 return AnimatableNumber::create(m_number * factor, m_unitType); | |
163 } | |
164 | |
165 AnimatableNumber::NumberUnitType AnimatableNumber::primitiveUnitToNumberType(uns
igned short primitiveUnit) | |
166 { | |
167 switch (primitiveUnit) { | |
168 case CSSPrimitiveValue::CSS_NUMBER: | |
169 return UnitTypeNumber; | |
170 case CSSPrimitiveValue::CSS_PX: | |
171 case CSSPrimitiveValue::CSS_CM: | |
172 case CSSPrimitiveValue::CSS_MM: | |
173 case CSSPrimitiveValue::CSS_IN: | |
174 case CSSPrimitiveValue::CSS_PT: | |
175 case CSSPrimitiveValue::CSS_PC: | |
176 return UnitTypeLength; | |
177 case CSSPrimitiveValue::CSS_EMS: | |
178 return UnitTypeFontSize; | |
179 case CSSPrimitiveValue::CSS_EXS: | |
180 return UnitTypeFontXSize; | |
181 case CSSPrimitiveValue::CSS_REMS: | |
182 return UnitTypeRootFontSize; | |
183 case CSSPrimitiveValue::CSS_DEG: | |
184 case CSSPrimitiveValue::CSS_RAD: | |
185 case CSSPrimitiveValue::CSS_GRAD: | |
186 case CSSPrimitiveValue::CSS_TURN: | |
187 return UnitTypeAngle; | |
188 case CSSPrimitiveValue::CSS_PERCENTAGE: | |
189 return UnitTypePercentage; | |
190 case CSSPrimitiveValue::CSS_VW: | |
191 return UnitTypeViewportWidth; | |
192 case CSSPrimitiveValue::CSS_VH: | |
193 return UnitTypeViewportHeight; | |
194 case CSSPrimitiveValue::CSS_VMIN: | |
195 return UnitTypeViewportMin; | |
196 case CSSPrimitiveValue::CSS_VMAX: | |
197 return UnitTypeViewportMax; | |
198 case CSSPrimitiveValue::CSS_MS: | |
199 case CSSPrimitiveValue::CSS_S: | |
200 return UnitTypeTime; | |
201 case CSSPrimitiveValue::CSS_HZ: | |
202 case CSSPrimitiveValue::CSS_KHZ: | |
203 return UnitTypeFrequency; | |
204 case CSSPrimitiveValue::CSS_DPPX: | |
205 case CSSPrimitiveValue::CSS_DPI: | |
206 case CSSPrimitiveValue::CSS_DPCM: | |
207 return UnitTypeResolution; | |
208 default: | |
209 return UnitTypeInvalid; | |
210 } | |
211 } | |
212 | |
213 unsigned short AnimatableNumber::numberTypeToPrimitiveUnit(NumberUnitType number
Type) | |
214 { | |
215 switch (numberType) { | |
216 case UnitTypeNumber: | |
217 return CSSPrimitiveValue::CSS_NUMBER; | |
218 case UnitTypeLength: | |
219 return CSSPrimitiveValue::CSS_PX; | |
220 case UnitTypeFontSize: | |
221 return CSSPrimitiveValue::CSS_EMS; | |
222 case UnitTypeFontXSize: | |
223 return CSSPrimitiveValue::CSS_EXS; | |
224 case UnitTypeRootFontSize: | |
225 return CSSPrimitiveValue::CSS_REMS; | |
226 case UnitTypePercentage: | |
227 return CSSPrimitiveValue::CSS_PERCENTAGE; | |
228 case UnitTypeViewportWidth: | |
229 return CSSPrimitiveValue::CSS_VW; | |
230 case UnitTypeViewportHeight: | |
231 return CSSPrimitiveValue::CSS_VH; | |
232 case UnitTypeViewportMin: | |
233 return CSSPrimitiveValue::CSS_VMIN; | |
234 case UnitTypeViewportMax: | |
235 return CSSPrimitiveValue::CSS_VMAX; | |
236 case UnitTypeTime: | |
237 return CSSPrimitiveValue::CSS_MS; | |
238 case UnitTypeAngle: | |
239 return CSSPrimitiveValue::CSS_DEG; | |
240 case UnitTypeFrequency: | |
241 return CSSPrimitiveValue::CSS_HZ; | |
242 case UnitTypeResolution: | |
243 return CSSPrimitiveValue::CSS_DPPX; | |
244 case UnitTypeInvalid: | |
245 return CSSPrimitiveValue::CSS_UNKNOWN; | |
246 } | |
247 ASSERT_NOT_REACHED(); | |
248 return CSSPrimitiveValue::CSS_UNKNOWN; | |
249 } | |
250 | |
251 } // namespace WebCore | |
OLD | NEW |