Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / Length.h
1 /*
2     Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3     Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
4     Copyright (C) 2011 Rik Cabanier (cabanier@adobe.com)
5     Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
6
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22
23 #ifndef Length_h
24 #define Length_h
25
26 #include "platform/PlatformExport.h"
27 #include "platform/animation/AnimationUtilities.h"
28 #include "wtf/Assertions.h"
29 #include "wtf/FastAllocBase.h"
30 #include "wtf/Forward.h"
31 #include "wtf/HashMap.h"
32 #include "wtf/MathExtras.h"
33 #include "wtf/Vector.h"
34 #include <cstring>
35
36 namespace blink {
37
38 // FIXME: This enum makes it hard to tell in general what values may be
39 // appropriate for any given Length.
40 enum LengthType {
41     Auto, Percent, Fixed,
42     Intrinsic, MinIntrinsic,
43     MinContent, MaxContent, FillAvailable, FitContent,
44     Calculated,
45     ExtendToZoom, DeviceWidth, DeviceHeight,
46     MaxSizeNone
47 };
48
49 enum ValueRange {
50     ValueRangeAll,
51     ValueRangeNonNegative
52 };
53
54 struct PixelsAndPercent {
55     PixelsAndPercent(float pixels, float percent)
56         : pixels(pixels)
57         , percent(percent)
58     {
59     }
60     float pixels;
61     float percent;
62 };
63
64 class CalculationValue;
65
66 class PLATFORM_EXPORT Length {
67     WTF_MAKE_FAST_ALLOCATED;
68 public:
69     Length()
70         :  m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false)
71     {
72     }
73
74     Length(LengthType t)
75         : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false)
76     {
77         ASSERT(t != Calculated);
78     }
79
80     Length(int v, LengthType t, bool q = false)
81         : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false)
82     {
83         ASSERT(t != Calculated);
84     }
85
86     Length(LayoutUnit v, LengthType t, bool q = false)
87         : m_floatValue(v.toFloat()), m_quirk(q), m_type(t), m_isFloat(true)
88     {
89         ASSERT(t != Calculated);
90     }
91
92     Length(float v, LengthType t, bool q = false)
93         : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
94     {
95         ASSERT(t != Calculated);
96     }
97
98     Length(double v, LengthType t, bool q = false)
99         : m_quirk(q), m_type(t), m_isFloat(true)
100     {
101         m_floatValue = static_cast<float>(v);
102     }
103
104     explicit Length(PassRefPtr<CalculationValue>);
105
106     Length(const Length& length)
107     {
108         memcpy(this, &length, sizeof(Length));
109         if (isCalculated())
110             incrementCalculatedRef();
111     }
112
113     Length& operator=(const Length& length)
114     {
115         if (length.isCalculated())
116             length.incrementCalculatedRef();
117         if (isCalculated())
118             decrementCalculatedRef();
119         memcpy(this, &length, sizeof(Length));
120         return *this;
121     }
122
123 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
124     Length(Length&& length)
125     {
126         memcpy(this, &length, sizeof(Length));
127
128         // Reset |length|'s type to Auto to make sure its destructor
129         // won't call decrementCalculatedRef() as we don't call
130         // incrementCalculatedRef() here.
131         length.m_type = Auto;
132     }
133
134     Length& operator=(Length&& length)
135     {
136         if (this == &length)
137             return *this;
138
139         if (isCalculated())
140             decrementCalculatedRef();
141
142         memcpy(this, &length, sizeof(Length));
143
144         // Reset |length|'s type to Auto to make sure its destructor
145         // won't call decrementCalculatedRef() as we don't call
146         // incrementCalculatedRef() here.
147         length.m_type = Auto;
148
149         return *this;
150     }
151 #endif
152
153     ~Length()
154     {
155         if (isCalculated())
156             decrementCalculatedRef();
157     }
158
159     bool operator==(const Length& o) const { return (m_type == o.m_type) && (m_quirk == o.m_quirk) && (isMaxSizeNone() || (getFloatValue() == o.getFloatValue()) || isCalculatedEqual(o)); }
160     bool operator!=(const Length& o) const { return !(*this == o); }
161
162     const Length& operator*=(float v)
163     {
164         if (isCalculated()) {
165             ASSERT_NOT_REACHED();
166             return *this;
167         }
168
169         if (m_isFloat)
170             m_floatValue = static_cast<float>(m_floatValue * v);
171         else
172             m_intValue = static_cast<int>(m_intValue * v);
173
174         return *this;
175     }
176
177     inline float value() const
178     {
179         return getFloatValue();
180     }
181
182     int intValue() const
183     {
184         if (isCalculated()) {
185             ASSERT_NOT_REACHED();
186             return 0;
187         }
188         return getIntValue();
189     }
190
191     float percent() const
192     {
193         ASSERT(type() == Percent);
194         return getFloatValue();
195     }
196     PixelsAndPercent pixelsAndPercent() const;
197
198     CalculationValue& calculationValue() const;
199
200     LengthType type() const { return static_cast<LengthType>(m_type); }
201     bool quirk() const { return m_quirk; }
202
203     void setQuirk(bool quirk)
204     {
205         m_quirk = quirk;
206     }
207
208     void setValue(LengthType t, int value)
209     {
210         m_type = t;
211         m_intValue = value;
212         m_isFloat = false;
213     }
214
215     void setValue(int value)
216     {
217         if (isCalculated()) {
218             ASSERT_NOT_REACHED();
219             return;
220         }
221         setValue(Fixed, value);
222     }
223
224     void setValue(LengthType t, float value)
225     {
226         m_type = t;
227         m_floatValue = value;
228         m_isFloat = true;
229     }
230
231     void setValue(LengthType t, LayoutUnit value)
232     {
233         m_type = t;
234         m_floatValue = value.toFloat();
235         m_isFloat = true;
236     }
237
238     void setValue(float value)
239     {
240         *this = Length(value, Fixed);
241     }
242
243     bool isMaxSizeNone() const { return type() == MaxSizeNone; }
244
245     // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length
246     // always contains a percentage, and without a maxValue passed to these functions
247     // it's impossible to determine the sign or zero-ness. We assume all calc values
248     // are positive and non-zero for now.
249     bool isZero() const
250     {
251         ASSERT(!isMaxSizeNone());
252         if (isCalculated())
253             return false;
254
255         return m_isFloat ? !m_floatValue : !m_intValue;
256     }
257     bool isPositive() const
258     {
259         if (isMaxSizeNone())
260             return false;
261         if (isCalculated())
262             return true;
263
264         return getFloatValue() > 0;
265     }
266     bool isNegative() const
267     {
268         if (isMaxSizeNone() || isCalculated())
269             return false;
270
271         return getFloatValue() < 0;
272     }
273
274     bool isAuto() const { return type() == Auto; }
275     bool isPercent() const { return type() == Percent || type() == Calculated; }
276     bool isFixed() const { return type() == Fixed; }
277     bool isIntrinsicOrAuto() const { return type() == Auto || isLegacyIntrinsic() || isIntrinsic(); }
278     bool isLegacyIntrinsic() const { return type() == Intrinsic || type() == MinIntrinsic; }
279     bool isIntrinsic() const { return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent; }
280     bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated; }
281     bool isSpecifiedOrIntrinsic() const { return isSpecified() || isIntrinsic(); }
282     bool isCalculated() const { return type() == Calculated; }
283     bool isCalculatedEqual(const Length&) const;
284     bool isMinContent() const { return type() == MinContent; }
285     bool isMaxContent() const { return type() == MaxContent; }
286     bool isFillAvailable() const { return type() == FillAvailable; }
287     bool isFitContent() const { return type() == FitContent; }
288
289     Length blend(const Length& from, double progress, ValueRange range) const
290     {
291         ASSERT(isSpecified() && from.isSpecified());
292
293         if (progress == 0.0)
294             return from;
295
296         if (progress == 1.0)
297             return *this;
298
299         if (from.type() == Calculated || type() == Calculated)
300             return blendMixedTypes(from, progress, range);
301
302         if (!from.isZero() && !isZero() && from.type() != type())
303             return blendMixedTypes(from, progress, range);
304
305         if (from.isZero() && isZero())
306             return *this;
307
308         LengthType resultType = type();
309         if (isZero())
310             resultType = from.type();
311
312         float blendedValue = blink::blend(from.value(), value(), progress);
313         if (range == ValueRangeNonNegative)
314             blendedValue = clampTo<float>(blendedValue, 0);
315         return Length(blendedValue, resultType);
316     }
317
318     float getFloatValue() const
319     {
320         ASSERT(!isMaxSizeNone());
321         return m_isFloat ? m_floatValue : m_intValue;
322     }
323     float nonNanCalculatedValue(int maxValue) const;
324
325     Length subtractFromOneHundredPercent() const;
326
327 private:
328     int getIntValue() const
329     {
330         ASSERT(!isMaxSizeNone());
331         return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
332     }
333
334     Length blendMixedTypes(const Length& from, double progress, ValueRange) const;
335
336     int calculationHandle() const
337     {
338         ASSERT(isCalculated());
339         return getIntValue();
340     }
341     void incrementCalculatedRef() const;
342     void decrementCalculatedRef() const;
343
344     union {
345         int m_intValue;
346         float m_floatValue;
347     };
348     bool m_quirk;
349     unsigned char m_type;
350     bool m_isFloat;
351 };
352
353 PLATFORM_EXPORT Vector<Length> parseHTMLAreaElementCoords(const String&);
354
355 } // namespace blink
356
357 #endif // Length_h