Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / animation / AnimatableLength.cpp
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/AnimatableLength.h"
33
34 #include "core/css/CSSPrimitiveValueMappings.h"
35 #include "platform/CalculationValue.h"
36 #include "platform/animation/AnimationUtilities.h"
37
38 namespace WebCore {
39
40 PassRefPtr<AnimatableLength> AnimatableLength::create(CSSValue* value)
41 {
42     ASSERT(canCreateFrom(value));
43     if (value->isPrimitiveValue()) {
44         CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(value);
45         const CSSCalcValue* calcValue = primitiveValue->cssCalcValue();
46         if (calcValue)
47             return create(calcValue->expressionNode(), primitiveValue);
48         NumberUnitType unitType;
49         bool isPrimitiveLength = primitiveUnitToNumberType(primitiveValue->primitiveType(), unitType);
50         ASSERT_UNUSED(isPrimitiveLength, isPrimitiveLength);
51         const double scale = CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(primitiveValue->primitiveType());
52         return create(primitiveValue->getDoubleValue() * scale, unitType, primitiveValue);
53     }
54
55     if (value->isCalcValue())
56         return create(toCSSCalcValue(value)->expressionNode());
57
58     ASSERT_NOT_REACHED();
59     return 0;
60 }
61
62 bool AnimatableLength::canCreateFrom(const CSSValue* value)
63 {
64     ASSERT(value);
65     if (value->isPrimitiveValue()) {
66         const CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(value);
67         if (primitiveValue->cssCalcValue())
68             return true;
69
70         NumberUnitType unitType;
71         // Only returns true if the type is a primitive length unit.
72         return primitiveUnitToNumberType(primitiveValue->primitiveType(), unitType);
73     }
74     return value->isCalcValue();
75 }
76
77 PassRefPtr<CSSValue> AnimatableLength::toCSSValue(NumberRange range) const
78 {
79     return toCSSPrimitiveValue(range);
80 }
81
82 Length AnimatableLength::toLength(const CSSToLengthConversionData& conversionData, NumberRange range) const
83 {
84     // Avoid creating a CSSValue in the common cases
85     if (m_unitType == UnitTypePixels)
86         return Length(clampedNumber(range) * conversionData.zoom(), Fixed);
87     if (m_unitType == UnitTypePercentage)
88         return Length(clampedNumber(range), Percent);
89
90     return toCSSPrimitiveValue(range)->convertToLength<AnyConversion>(conversionData);
91 }
92
93 bool AnimatableLength::usesDefaultInterpolationWith(const AnimatableValue* value) const
94 {
95     const AnimatableLength* length = toAnimatableLength(value);
96     NumberUnitType type = commonUnitType(length);
97     return type == UnitTypeCalc && (isViewportUnit() || length->isViewportUnit());
98 }
99
100 PassRefPtr<AnimatableValue> AnimatableLength::interpolateTo(const AnimatableValue* value, double fraction) const
101 {
102     const AnimatableLength* length = toAnimatableLength(value);
103     NumberUnitType type = commonUnitType(length);
104     if (type != UnitTypeCalc)
105         return AnimatableLength::create(blend(m_number, length->m_number, fraction), type);
106
107     // FIXME(crbug.com/168840): Support for viewport units in calc needs to be added before we can blend them with other units.
108     if (isViewportUnit() || length->isViewportUnit())
109         return defaultInterpolateTo(this, value, fraction);
110
111     return AnimatableLength::create(scale(1 - fraction).get(), length->scale(fraction).get());
112 }
113
114 PassRefPtr<AnimatableValue> AnimatableLength::addWith(const AnimatableValue* value) const
115 {
116     // Optimization for adding with 0.
117     if (isUnitlessZero())
118         return takeConstRef(value);
119
120     const AnimatableLength* length = toAnimatableLength(value);
121     if (length->isUnitlessZero())
122         return takeConstRef(this);
123
124     NumberUnitType type = commonUnitType(length);
125     if (type != UnitTypeCalc)
126         return AnimatableLength::create(m_number + length->m_number, type);
127
128     return AnimatableLength::create(this, length);
129 }
130
131 bool AnimatableLength::equalTo(const AnimatableValue* value) const
132 {
133     const AnimatableLength* length = toAnimatableLength(value);
134     if (m_unitType != length->m_unitType)
135         return false;
136     if (isCalc())
137         return m_calcExpression == length->m_calcExpression || m_calcExpression->equals(*length->m_calcExpression);
138     return m_number == length->m_number;
139 }
140
141 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> AnimatableLength::toCSSCalcExpressionNode() const
142 {
143     if (isCalc())
144         return m_calcExpression;
145     return CSSCalcValue::createExpressionNode(toCSSPrimitiveValue(AllValues), m_number == trunc(m_number));
146 }
147
148 static bool isCompatibleWithRange(const CSSPrimitiveValue* primitiveValue, NumberRange range)
149 {
150     ASSERT(primitiveValue);
151     if (range == AllValues)
152         return true;
153     if (primitiveValue->isCalculated())
154         return primitiveValue->cssCalcValue()->permittedValueRange() == ValueRangeNonNegative;
155     return primitiveValue->getDoubleValue() >= 0;
156 }
157
158 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> AnimatableLength::toCSSPrimitiveValue(NumberRange range) const
159 {
160     if (!m_cachedCSSPrimitiveValue || !isCompatibleWithRange(m_cachedCSSPrimitiveValue.get(), range)) {
161         if (isCalc())
162             m_cachedCSSPrimitiveValue = CSSPrimitiveValue::create(CSSCalcValue::create(m_calcExpression, range == AllValues ? ValueRangeAll : ValueRangeNonNegative));
163         else
164             m_cachedCSSPrimitiveValue = CSSPrimitiveValue::create(clampedNumber(range), static_cast<CSSPrimitiveValue::UnitTypes>(numberTypeToPrimitiveUnit(m_unitType)));
165     }
166     return m_cachedCSSPrimitiveValue;
167 }
168
169 PassRefPtr<AnimatableLength> AnimatableLength::scale(double factor) const
170 {
171     if (isCalc()) {
172         return AnimatableLength::create(CSSCalcValue::createExpressionNode(
173             m_calcExpression,
174             CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(factor, CSSPrimitiveValue::CSS_NUMBER)),
175             CalcMultiply));
176     }
177     return AnimatableLength::create(m_number * factor, m_unitType);
178 }
179
180 bool AnimatableLength::primitiveUnitToNumberType(unsigned short primitiveUnit, NumberUnitType& numberType)
181 {
182     switch (primitiveUnit) {
183     case CSSPrimitiveValue::CSS_PX:
184     case CSSPrimitiveValue::CSS_CM:
185     case CSSPrimitiveValue::CSS_MM:
186     case CSSPrimitiveValue::CSS_IN:
187     case CSSPrimitiveValue::CSS_PT:
188     case CSSPrimitiveValue::CSS_PC:
189         numberType = UnitTypePixels;
190         return true;
191     case CSSPrimitiveValue::CSS_EMS:
192         numberType = UnitTypeFontSize;
193         return true;
194     case CSSPrimitiveValue::CSS_EXS:
195         numberType = UnitTypeFontXSize;
196         return true;
197     case CSSPrimitiveValue::CSS_REMS:
198         numberType = UnitTypeRootFontSize;
199         return true;
200     case CSSPrimitiveValue::CSS_PERCENTAGE:
201         numberType = UnitTypePercentage;
202         return true;
203     case CSSPrimitiveValue::CSS_VW:
204         numberType = UnitTypeViewportWidth;
205         return true;
206     case CSSPrimitiveValue::CSS_VH:
207         numberType = UnitTypeViewportHeight;
208         return true;
209     case CSSPrimitiveValue::CSS_VMIN:
210         numberType = UnitTypeViewportMin;
211         return true;
212     case CSSPrimitiveValue::CSS_VMAX:
213         numberType = UnitTypeViewportMax;
214         return true;
215     default:
216         return false;
217     }
218 }
219
220 unsigned short AnimatableLength::numberTypeToPrimitiveUnit(NumberUnitType numberType)
221 {
222     switch (numberType) {
223     case UnitTypePixels:
224         return CSSPrimitiveValue::CSS_PX;
225     case UnitTypeFontSize:
226         return CSSPrimitiveValue::CSS_EMS;
227     case UnitTypeFontXSize:
228         return CSSPrimitiveValue::CSS_EXS;
229     case UnitTypeRootFontSize:
230         return CSSPrimitiveValue::CSS_REMS;
231     case UnitTypePercentage:
232         return CSSPrimitiveValue::CSS_PERCENTAGE;
233     case UnitTypeViewportWidth:
234         return CSSPrimitiveValue::CSS_VW;
235     case UnitTypeViewportHeight:
236         return CSSPrimitiveValue::CSS_VH;
237     case UnitTypeViewportMin:
238         return CSSPrimitiveValue::CSS_VMIN;
239     case UnitTypeViewportMax:
240         return CSSPrimitiveValue::CSS_VMAX;
241     case UnitTypeCalc:
242         return CSSPrimitiveValue::CSS_UNKNOWN;
243     }
244     ASSERT_NOT_REACHED();
245     return CSSPrimitiveValue::CSS_UNKNOWN;
246 }
247
248 } // namespace WebCore