Name all the GLib timeout sources
[WebKit-https.git] / Source / WebCore / 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 "AnimationUtilities.h"
27 #include <memory>
28 #include <string.h>
29 #include <wtf/Assertions.h>
30 #include <wtf/FastMalloc.h>
31 #include <wtf/Forward.h>
32 #include <wtf/HashMap.h>
33 #include <wtf/MathExtras.h>
34
35 namespace WebCore {
36
37 enum LengthType {
38     Auto, Relative, Percent, Fixed,
39     Intrinsic, MinIntrinsic,
40     MinContent, MaxContent, FillAvailable, FitContent,
41     Calculated,
42     ViewportPercentageWidth, ViewportPercentageHeight, ViewportPercentageMin, ViewportPercentageMax,
43     Undefined
44 };
45
46 class CalculationValue;    
47     
48 struct Length {
49     WTF_MAKE_FAST_ALLOCATED;
50 public:
51     Length()
52         :  m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false)
53     {
54     }
55
56     Length(LengthType t)
57         : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false)
58     {
59         ASSERT(t != Calculated);
60     }
61
62     Length(int v, LengthType t, bool q = false)
63         : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false)
64     {
65         ASSERT(t != Calculated);
66     }
67     
68     Length(LayoutUnit v, LengthType t, bool q = false)
69         : m_floatValue(v.toFloat()), m_quirk(q), m_type(t), m_isFloat(true)
70     {
71         ASSERT(t != Calculated);
72     }
73     
74     Length(float v, LengthType t, bool q = false)
75         : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
76     {
77         ASSERT(t != Calculated);
78     }
79
80     Length(double v, LengthType t, bool q = false)
81         : m_quirk(q), m_type(t), m_isFloat(true)
82     {
83         m_floatValue = static_cast<float>(v);    
84     }
85
86     explicit Length(PassRefPtr<CalculationValue>);
87
88     Length(const Length& length)
89     {
90         initFromLength(length);
91     }
92
93     Length(Length&& other)
94     {
95         moveFromLength(std::move(other));
96     }
97
98     Length& operator=(const Length& length)
99     {
100         initFromLength(length);
101         return *this;
102     }
103
104     Length& operator=(Length&& other)
105     {
106         if (this != &other)
107             moveFromLength(std::move(other));
108         return *this;
109     }
110
111     ~Length()
112     {
113         if (isCalculated())
114             decrementCalculatedRef();
115     }  
116     
117     bool operator==(const Length& o) const { return (m_type == o.m_type) && (m_quirk == o.m_quirk) && (isUndefined() || (getFloatValue() == o.getFloatValue()) || isCalculatedEqual(o)); }
118     bool operator!=(const Length& o) const { return !(*this == o); }
119
120     const Length& operator*=(float v)
121     {       
122         if (isCalculated()) {
123             ASSERT_NOT_REACHED();
124             return *this;
125         }
126         
127         if (m_isFloat)
128             m_floatValue = static_cast<float>(m_floatValue * v);
129         else        
130             m_intValue = static_cast<int>(m_intValue * v);
131         
132         return *this;
133     }
134     
135     inline float value() const
136     {
137         return getFloatValue();
138     }
139
140      int intValue() const
141      {
142         if (isCalculated()) {
143             ASSERT_NOT_REACHED();
144             return 0;
145         }
146         return getIntValue();
147     }
148
149     float percent() const
150     {
151         ASSERT(isPercent());
152         return getFloatValue();
153     }
154
155     PassRefPtr<CalculationValue> calculationValue() const;
156
157     LengthType type() const { return static_cast<LengthType>(m_type); }
158     bool quirk() const { return m_quirk; }
159
160     void setQuirk(bool quirk)
161     {
162         m_quirk = quirk;
163     }
164
165     void setValue(LengthType t, int value)
166     {
167         m_type = t;
168         m_intValue = value;
169         m_isFloat = false;
170     }
171
172     void setValue(int value)
173     {
174         if (isCalculated()) {
175             ASSERT_NOT_REACHED();
176             return;
177         }
178         setValue(Fixed, value);
179     }
180
181     void setValue(LengthType t, float value)
182     {
183         m_type = t;
184         m_floatValue = value;
185         m_isFloat = true;    
186     }
187
188     void setValue(LengthType t, LayoutUnit value)
189     {
190         m_type = t;
191         m_floatValue = value;
192         m_isFloat = true;    
193     }
194
195     void setValue(float value)
196     {
197         *this = Length(value, Fixed);
198     }
199
200     bool isUndefined() const { return type() == Undefined; }
201
202     // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length 
203     // always contains a percentage, and without a maxValue passed to these functions
204     // it's impossible to determine the sign or zero-ness. We assume all calc values
205     // are positive and non-zero for now.    
206     bool isZero() const 
207     {
208         ASSERT(!isUndefined());
209         if (isCalculated())
210             return false;
211             
212         return m_isFloat ? !m_floatValue : !m_intValue;
213     }
214     bool isPositive() const
215     {
216         if (isUndefined())
217             return false;
218         if (isCalculated())
219             return true;
220                 
221         return getFloatValue() > 0;
222     }
223     bool isNegative() const
224     {
225         if (isUndefined() || isCalculated())
226             return false;
227             
228         return getFloatValue() < 0;
229     }
230     
231     bool isAuto() const { return type() == Auto; }
232     bool isRelative() const { return type() == Relative; }
233     bool isPercent() const { return type() == Percent || type() == Calculated; }
234     bool isFixed() const { return type() == Fixed; }
235     bool isIntrinsicOrAuto() const { return type() == Auto || isLegacyIntrinsic() || isIntrinsic(); }
236     bool isLegacyIntrinsic() const { return type() == Intrinsic || type() == MinIntrinsic; }
237     bool isIntrinsic() const { return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent; }
238     bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated || isViewportPercentage(); }
239     bool isSpecifiedOrIntrinsic() const { return isSpecified() || isIntrinsic(); }
240     bool isCalculated() const { return type() == Calculated; }
241     bool isCalculatedEqual(const Length&) const;
242     bool isMinContent() const { return type() == MinContent; }
243     bool isMaxContent() const { return type() == MaxContent; }
244
245     Length blend(const Length& from, double progress) const
246     {
247         // Blend two lengths to produce a new length that is in between them.  Used for animation.
248         if (from.type() == Calculated || type() == Calculated)
249             return blendMixedTypes(from, progress);
250         
251         if (!from.isZero() && !isZero() && from.type() != type())
252             return blendMixedTypes(from, progress);
253
254         if (from.isZero() && isZero())
255             return *this;
256         
257         LengthType resultType = type();
258         if (isZero())
259             resultType = from.type();
260         
261         if (resultType == Percent) {
262             float fromPercent = from.isZero() ? 0 : from.percent();
263             float toPercent = isZero() ? 0 : percent();
264             return Length(WebCore::blend(fromPercent, toPercent, progress), Percent);
265         } 
266
267         float fromValue = from.isZero() ? 0 : from.value();
268         float toValue = isZero() ? 0 : value();
269         return Length(WebCore::blend(fromValue, toValue, progress), resultType);
270     }
271
272     float getFloatValue() const
273     {
274         ASSERT(!isUndefined());
275         return m_isFloat ? m_floatValue : m_intValue;
276     }
277     float nonNanCalculatedValue(int maxValue) const;
278
279     bool isViewportPercentage() const
280     {
281         LengthType lengthType = type();
282         return lengthType >= ViewportPercentageWidth && lengthType <= ViewportPercentageMax;
283     }
284     float viewportPercentageLength() const
285     {
286         ASSERT(isViewportPercentage());
287         return getFloatValue();
288     }
289 private:
290     int getIntValue() const
291     {
292         ASSERT(!isUndefined());
293         return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
294     }
295     void initFromLength(const Length& length)
296     {
297         memcpy(this, &length, sizeof(Length));
298         if (isCalculated())
299             incrementCalculatedRef();
300     }
301
302     void moveFromLength(Length&& length)
303     {
304         ASSERT(this != &length);
305         memcpy(this, &length, sizeof(Length));
306         length.m_type = Auto;
307     }
308
309     Length blendMixedTypes(const Length& from, double progress) const;
310
311     int calculationHandle() const
312     {
313         ASSERT(isCalculated());
314         return getIntValue();
315     }
316     void incrementCalculatedRef() const;
317     void decrementCalculatedRef() const;    
318     
319     union {
320         int m_intValue;
321         float m_floatValue;
322     };
323     bool m_quirk;
324     unsigned char m_type;
325     bool m_isFloat;
326 };
327
328 std::unique_ptr<Length[]> newCoordsArray(const String&, int& len);
329 std::unique_ptr<Length[]> newLengthArray(const String&, int& len);
330
331 } // namespace WebCore
332
333 #endif // Length_h