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