Migrate from ints to unsigneds when referring to indices into strings
[WebKit-https.git] / Source / WebCore / platform / Length.h
1 /*
2     Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3     Copyright (C) 2006, 2008, 2014 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
33 namespace WebCore {
34
35 enum LengthType {
36     Auto, Relative, Percent, Fixed,
37     Intrinsic, MinIntrinsic,
38     MinContent, MaxContent, FillAvailable, FitContent,
39     Calculated,
40     Undefined
41 };
42
43 class CalculationValue;
44 class TextStream;
45
46 struct Length {
47     WTF_MAKE_FAST_ALLOCATED;
48 public:
49     Length(LengthType = Auto);
50
51     Length(int value, LengthType, bool hasQuirk = false);
52     Length(LayoutUnit value, LengthType, bool hasQuirk = false);
53     Length(float value, LengthType, bool hasQuirk = false);
54     Length(double value, LengthType, bool hasQuirk = false);
55
56     WEBCORE_EXPORT explicit Length(Ref<CalculationValue>&&);
57
58     Length(const Length&);
59     Length(Length&&);
60     Length& operator=(const Length&);
61     Length& operator=(Length&&);
62
63     ~Length();
64
65     void setValue(LengthType, int value);
66     void setValue(LengthType, float value);
67     void setValue(LengthType, LayoutUnit value);
68     Length& operator*=(float);
69
70     void setHasQuirk(bool);
71
72     bool operator==(const Length&) const;
73     bool operator!=(const Length&) const;
74
75     float value() const;
76     int intValue() const;
77     float percent() const;
78     CalculationValue& calculationValue() const;
79
80     LengthType type() const;
81
82     bool isAuto() const;
83     bool isCalculated() const;
84     bool isFixed() const;
85     bool isMaxContent() const;
86     bool isMinContent() const;
87     bool isPercent() const;
88     bool isRelative() const;
89     bool isUndefined() const;
90     bool isFillAvailable() const;
91     bool isFitContent() const;
92
93     bool hasQuirk() const;
94
95     // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length
96     // always contains a percentage, and without a maxValue passed to these functions
97     // it's impossible to determine the sign or zero-ness. The following three functions
98     // act as if all calculated values are positive.
99     bool isZero() const;
100     bool isPositive() const;
101     bool isNegative() const;
102
103     bool isPercentOrCalculated() const; // Returns true for both Percent and Calculated.
104
105     bool isIntrinsic() const;
106     bool isIntrinsicOrAuto() const;
107     bool isSpecified() const;
108     bool isSpecifiedOrIntrinsic() const;
109
110     float nonNanCalculatedValue(int maxValue) const;
111
112 private:
113     bool isLegacyIntrinsic() const;
114
115     bool isCalculatedEqual(const Length&) const;
116
117     WEBCORE_EXPORT void ref() const;
118     WEBCORE_EXPORT void deref() const;
119     
120     union {
121         int m_intValue;
122         float m_floatValue;
123         unsigned m_calculationValueHandle;
124     };
125     bool m_hasQuirk;
126     unsigned char m_type;
127     bool m_isFloat;
128 };
129
130 // Blend two lengths to produce a new length that is in between them. Used for animation.
131 Length blend(const Length& from, const Length& to, double progress);
132
133 std::unique_ptr<Length[]> newCoordsArray(const String&, int& length);
134 std::unique_ptr<Length[]> newLengthArray(const String&, int& length);
135
136 inline Length::Length(LengthType type)
137     : m_intValue(0), m_hasQuirk(false), m_type(type), m_isFloat(false)
138 {
139     ASSERT(type != Calculated);
140 }
141
142 inline Length::Length(int value, LengthType type, bool hasQuirk)
143     : m_intValue(value), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(false)
144 {
145     ASSERT(type != Calculated);
146 }
147
148 inline Length::Length(LayoutUnit value, LengthType type, bool hasQuirk)
149     : m_floatValue(value.toFloat()), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
150 {
151     ASSERT(type != Calculated);
152 }
153
154 inline Length::Length(float value, LengthType type, bool hasQuirk)
155     : m_floatValue(value), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
156 {
157     ASSERT(type != Calculated);
158 }
159
160 inline Length::Length(double value, LengthType type, bool hasQuirk)
161     : m_floatValue(static_cast<float>(value)), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
162 {
163     ASSERT(type != Calculated);
164 }
165
166 inline Length::Length(const Length& other)
167 {
168     if (other.isCalculated())
169         other.ref();
170
171     memcpy(this, &other, sizeof(Length));
172 }
173
174 inline Length::Length(Length&& other)
175 {
176     memcpy(this, &other, sizeof(Length));
177     other.m_type = Auto;
178 }
179
180 inline Length& Length::operator=(const Length& other)
181 {
182     if (this == &other)
183         return *this;
184
185     if (other.isCalculated())
186         other.ref();
187     if (isCalculated())
188         deref();
189
190     memcpy(this, &other, sizeof(Length));
191     return *this;
192 }
193
194 inline Length& Length::operator=(Length&& other)
195 {
196     if (this == &other)
197         return *this;
198
199     if (isCalculated())
200         deref();
201
202     memcpy(this, &other, sizeof(Length));
203     other.m_type = Auto;
204     return *this;
205 }
206
207 inline Length::~Length()
208 {
209     if (isCalculated())
210         deref();
211 }
212
213 inline bool Length::operator==(const Length& other) const
214 {
215     // FIXME: This might be too long to be inline.
216     if (type() != other.type() || hasQuirk() != other.hasQuirk())
217         return false;
218     if (isUndefined())
219         return true;
220     if (isCalculated())
221         return isCalculatedEqual(other);
222     return value() == other.value();
223 }
224
225 inline bool Length::operator!=(const Length& other) const
226 {
227     return !(*this == other);
228 }
229
230 inline Length& Length::operator*=(float value)
231 {
232     ASSERT(!isCalculated());
233     if (isCalculated())
234         return *this;
235
236     if (m_isFloat)
237         m_floatValue *= value;
238     else
239         m_intValue *= value;
240
241     return *this;
242 }
243
244 inline float Length::value() const
245 {
246     ASSERT(!isUndefined());
247     ASSERT(!isCalculated());
248     return m_isFloat ? m_floatValue : m_intValue;
249 }
250
251 inline int Length::intValue() const
252 {
253     ASSERT(!isUndefined());
254     ASSERT(!isCalculated());
255     // FIXME: Makes no sense to return 0 here but not in the value() function above.
256     if (isCalculated())
257         return 0;
258     return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
259 }
260
261 inline float Length::percent() const
262 {
263     ASSERT(isPercent());
264     return value();
265 }
266
267 inline LengthType Length::type() const
268 {
269     return static_cast<LengthType>(m_type);
270 }
271
272 inline bool Length::hasQuirk() const
273 {
274     return m_hasQuirk;
275 }
276
277 inline void Length::setHasQuirk(bool hasQuirk)
278 {
279     m_hasQuirk = hasQuirk;
280 }
281
282 inline void Length::setValue(LengthType type, int value)
283 {
284     ASSERT(m_type != Calculated);
285     ASSERT(type != Calculated);
286     m_type = type;
287     m_intValue = value;
288     m_isFloat = false;
289 }
290
291 inline void Length::setValue(LengthType type, float value)
292 {
293     ASSERT(m_type != Calculated);
294     ASSERT(type != Calculated);
295     m_type = type;
296     m_floatValue = value;
297     m_isFloat = true;
298 }
299
300 inline void Length::setValue(LengthType type, LayoutUnit value)
301 {
302     ASSERT(m_type != Calculated);
303     ASSERT(type != Calculated);
304     m_type = type;
305     m_floatValue = value;
306     m_isFloat = true;
307 }
308
309 inline bool Length::isAuto() const
310 {
311     return type() == Auto;
312 }
313
314 inline bool Length::isFixed() const
315 {
316     return type() == Fixed;
317 }
318
319 inline bool Length::isMaxContent() const
320 {
321     return type() == MaxContent;
322 }
323
324 inline bool Length::isMinContent() const
325 {
326     return type() == MinContent;
327 }
328
329 inline bool Length::isNegative() const
330 {
331     if (isUndefined() || isCalculated())
332         return false;
333     return m_isFloat ? (m_floatValue < 0) : (m_intValue < 0);
334 }
335
336 inline bool Length::isPercent() const
337 {
338     return type() == Percent;
339 }
340
341 inline bool Length::isRelative() const
342 {
343     return type() == Relative;
344 }
345
346 inline bool Length::isUndefined() const
347 {
348     return type() == Undefined;
349 }
350
351 inline bool Length::isPercentOrCalculated() const
352 {
353     return isPercent() || isCalculated();
354 }
355
356 inline bool Length::isPositive() const
357 {
358     if (isUndefined())
359         return false;
360     if (isCalculated())
361         return true;
362     return m_isFloat ? (m_floatValue > 0) : (m_intValue > 0);
363 }
364
365 inline bool Length::isZero() const
366 {
367     ASSERT(!isUndefined());
368     if (isCalculated())
369         return false;
370     return m_isFloat ? !m_floatValue : !m_intValue;
371 }
372
373 inline bool Length::isCalculated() const
374 {
375     return type() == Calculated;
376 }
377
378 inline bool Length::isLegacyIntrinsic() const
379 {
380     return type() == Intrinsic || type() == MinIntrinsic;
381 }
382
383 inline bool Length::isIntrinsic() const
384 {
385     return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent;
386 }
387
388 inline bool Length::isIntrinsicOrAuto() const
389 {
390     return isAuto() || isIntrinsic() || isLegacyIntrinsic();
391 }
392
393 inline bool Length::isSpecified() const
394 {
395     return isFixed() || isPercentOrCalculated();
396 }
397
398 inline bool Length::isSpecifiedOrIntrinsic() const
399 {
400     return isSpecified() || isIntrinsic();
401 }
402
403 inline bool Length::isFillAvailable() const
404 {
405     return type() == FillAvailable;
406 }
407
408 inline bool Length::isFitContent() const
409 {
410     return type() == FitContent;
411 }
412
413 TextStream& operator<<(TextStream&, Length);
414
415 } // namespace WebCore
416
417 #endif // Length_h