1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* representation of length values in computed style data */
8 #ifndef nsStyleCoord_h___
9 #define nsStyleCoord_h___
12 #include "nsStyleConsts.h"
14 enum nsStyleUnit
: uint8_t {
15 eStyleUnit_Null
= 0, // (no value) value is not specified
16 eStyleUnit_Normal
= 1, // (no value)
17 eStyleUnit_Auto
= 2, // (no value)
18 eStyleUnit_None
= 3, // (no value)
19 eStyleUnit_Percent
= 10, // (float) 1.0 == 100%
20 eStyleUnit_Factor
= 11, // (float) a multiplier
21 eStyleUnit_Degree
= 12, // (float) angle in degrees
22 eStyleUnit_Grad
= 13, // (float) angle in grads
23 eStyleUnit_Radian
= 14, // (float) angle in radians
24 eStyleUnit_Turn
= 15, // (float) angle in turns
25 eStyleUnit_FlexFraction
= 16, // (float) <flex> in fr units
26 eStyleUnit_Coord
= 20, // (nscoord) value is twips
27 eStyleUnit_Integer
= 30, // (int) value is simple integer
28 eStyleUnit_Enumerated
= 32, // (int) value has enumerated meaning
30 // The following are reference counted allocated types.
31 eStyleUnit_Calc
= 40, // (Calc*) calc() toplevel; always present
32 // to distinguish 50% from calc(50%), etc.
34 eStyleUnit_MAX
= 40 // highest valid nsStyleUnit value
38 int32_t mInt
; // nscoord is a int32_t for now
40 // An mPointer is a reference counted pointer. Currently this can only
41 // ever be an nsStyleCoord::Calc*.
46 * Class that hold a single size specification used by the style
47 * system. The size specification consists of two parts -- a number
48 * and a unit. The number is an integer, a floating point value, an
49 * nscoord, or undefined, and the unit is an nsStyleUnit. Checking
50 * the unit is a must before asking for the value in any particular
55 // Non-reference counted calc() value. See nsStyleStruct.h for some uses
58 // Every calc() expression evaluates to a length plus a percentage.
61 bool mHasPercent
; // whether there was any % syntax, even if 0
63 bool operator==(const CalcValue
& aOther
) const {
64 return mLength
== aOther
.mLength
&&
65 mPercent
== aOther
.mPercent
&&
66 mHasPercent
== aOther
.mHasPercent
;
68 bool operator!=(const CalcValue
& aOther
) const {
69 return !(*this == aOther
);
73 // Reference counted calc() value. This is the type that is used to store
74 // the calc() value in nsStyleCoord.
75 struct Calc MOZ_FINAL
: public CalcValue
{
76 NS_INLINE_DECL_REFCOUNTING(Calc
)
80 Calc(const Calc
&) = delete;
82 Calc
& operator=(const Calc
&) = delete;
85 explicit nsStyleCoord(nsStyleUnit aUnit
= eStyleUnit_Null
);
86 enum CoordConstructorType
{ CoordConstructor
};
87 inline nsStyleCoord(nscoord aValue
, CoordConstructorType
);
88 nsStyleCoord(int32_t aValue
, nsStyleUnit aUnit
);
89 nsStyleCoord(float aValue
, nsStyleUnit aUnit
);
90 inline nsStyleCoord(const nsStyleCoord
& aCopy
);
91 inline nsStyleCoord(const nsStyleUnion
& aValue
, nsStyleUnit aUnit
);
92 ~nsStyleCoord() { Reset(); }
94 nsStyleCoord
& operator=(const nsStyleCoord
& aOther
)
96 if (this != &aOther
) {
97 SetValue(mUnit
, mValue
, aOther
);
101 bool operator==(const nsStyleCoord
& aOther
) const;
102 bool operator!=(const nsStyleCoord
& aOther
) const;
104 nsStyleUnit
GetUnit() const {
105 NS_ASSERTION(mUnit
!= eStyleUnit_Null
, "reading uninitialized value");
109 bool IsAngleValue() const {
110 return eStyleUnit_Degree
<= mUnit
&& mUnit
<= eStyleUnit_Turn
;
113 static bool IsCalcUnit(nsStyleUnit aUnit
) {
114 return aUnit
== eStyleUnit_Calc
;
117 static bool IsPointerUnit(nsStyleUnit aUnit
) {
118 return IsCalcUnit(aUnit
);
121 bool IsCalcUnit() const {
122 return IsCalcUnit(mUnit
);
125 bool IsPointerValue() const {
126 return IsPointerUnit(mUnit
);
129 bool IsCoordPercentCalcUnit() const {
130 return mUnit
== eStyleUnit_Coord
||
131 mUnit
== eStyleUnit_Percent
||
135 // Does this calc() expression have any percentages inside it? Can be
136 // called only when IsCalcUnit() is true.
137 bool CalcHasPercent() const {
138 return GetCalcValue()->mHasPercent
;
141 bool HasPercent() const {
142 return mUnit
== eStyleUnit_Percent
||
143 (IsCalcUnit() && CalcHasPercent());
146 bool ConvertsToLength() const {
147 return mUnit
== eStyleUnit_Coord
||
148 (IsCalcUnit() && !CalcHasPercent());
151 nscoord
GetCoordValue() const;
152 int32_t GetIntValue() const;
153 float GetPercentValue() const;
154 float GetFactorValue() const;
155 float GetFactorOrPercentValue() const;
156 float GetAngleValue() const;
157 double GetAngleValueInDegrees() const;
158 double GetAngleValueInRadians() const;
159 float GetFlexFractionValue() const;
160 Calc
* GetCalcValue() const;
161 uint32_t HashValue(uint32_t aHash
) const;
163 // Sets to null and releases any refcounted objects. Only use this if the
164 // object is initialized (i.e. don't use it in nsStyleCoord constructors).
167 void SetCoordValue(nscoord aValue
);
168 void SetIntValue(int32_t aValue
, nsStyleUnit aUnit
);
169 void SetPercentValue(float aValue
);
170 void SetFactorValue(float aValue
);
171 void SetAngleValue(float aValue
, nsStyleUnit aUnit
);
172 void SetFlexFractionValue(float aValue
);
173 void SetNormalValue();
176 void SetCalcValue(Calc
* aValue
);
178 // Resets a coord represented by a unit/value pair.
179 static inline void Reset(nsStyleUnit
& aUnit
, nsStyleUnion
& aValue
);
181 // Sets a coord represented by a unit/value pair from a second
183 static inline void SetValue(nsStyleUnit
& aUnit
,
184 nsStyleUnion
& aValue
,
185 nsStyleUnit aOtherUnit
,
186 const nsStyleUnion
& aOtherValue
);
188 // Sets a coord represented by a unit/value pair from an nsStyleCoord.
189 static inline void SetValue(nsStyleUnit
& aUnit
, nsStyleUnion
& aValue
,
190 const nsStyleCoord
& aOther
);
198 * Class that represents a set of top/right/bottom/left nsStyleCoords.
199 * This is commonly used to hold the widths of the borders, margins,
200 * or paddings of a box.
205 nsStyleSides(const nsStyleSides
&);
208 nsStyleSides
& operator=(const nsStyleSides
& aCopy
);
209 bool operator==(const nsStyleSides
& aOther
) const;
210 bool operator!=(const nsStyleSides
& aOther
) const;
212 inline nsStyleUnit
GetUnit(mozilla::css::Side aSide
) const;
213 inline nsStyleUnit
GetLeftUnit() const;
214 inline nsStyleUnit
GetTopUnit() const;
215 inline nsStyleUnit
GetRightUnit() const;
216 inline nsStyleUnit
GetBottomUnit() const;
218 inline nsStyleCoord
Get(mozilla::css::Side aSide
) const;
219 inline nsStyleCoord
GetLeft() const;
220 inline nsStyleCoord
GetTop() const;
221 inline nsStyleCoord
GetRight() const;
222 inline nsStyleCoord
GetBottom() const;
224 // Sets each side to null and releases any refcounted objects. Only use this
225 // if the object is initialized (i.e. don't use it in nsStyleSides
229 inline void Set(mozilla::css::Side aSide
, const nsStyleCoord
& aCoord
);
230 inline void SetLeft(const nsStyleCoord
& aCoord
);
231 inline void SetTop(const nsStyleCoord
& aCoord
);
232 inline void SetRight(const nsStyleCoord
& aCoord
);
233 inline void SetBottom(const nsStyleCoord
& aCoord
);
236 nsStyleUnit mUnits
[4];
237 nsStyleUnion mValues
[4];
241 * Class that represents a set of top-left/top-right/bottom-left/bottom-right
242 * nsStyleCoord pairs. This is used to hold the dimensions of the
243 * corners of a box (for, e.g., border-radius and outline-radius).
245 class nsStyleCorners
{
248 nsStyleCorners(const nsStyleCorners
&);
251 // use compiler's version
252 nsStyleCorners
& operator=(const nsStyleCorners
& aCopy
);
253 bool operator==(const nsStyleCorners
& aOther
) const;
254 bool operator!=(const nsStyleCorners
& aOther
) const;
256 // aCorner is always one of NS_CORNER_* defined in nsStyleConsts.h
257 inline nsStyleUnit
GetUnit(uint8_t aHalfCorner
) const;
259 inline nsStyleCoord
Get(uint8_t aHalfCorner
) const;
261 // Sets each corner to null and releases any refcounted objects. Only use
262 // this if the object is initialized (i.e. don't use it in nsStyleCorners
266 inline void Set(uint8_t aHalfCorner
, const nsStyleCoord
& aCoord
);
269 nsStyleUnit mUnits
[8];
270 nsStyleUnion mValues
[8];
274 // -------------------------
275 // nsStyleCoord inlines
277 inline nsStyleCoord::nsStyleCoord(nscoord aValue
, CoordConstructorType
)
278 : mUnit(eStyleUnit_Coord
)
280 mValue
.mInt
= aValue
;
283 inline nsStyleCoord::nsStyleCoord(const nsStyleCoord
& aCopy
)
284 : mUnit(eStyleUnit_Null
)
286 SetValue(mUnit
, mValue
, aCopy
);
289 inline nsStyleCoord::nsStyleCoord(const nsStyleUnion
& aValue
, nsStyleUnit aUnit
)
290 : mUnit(eStyleUnit_Null
)
292 SetValue(mUnit
, mValue
, aUnit
, aValue
);
295 inline bool nsStyleCoord::operator!=(const nsStyleCoord
& aOther
) const
297 return !((*this) == aOther
);
300 inline nscoord
nsStyleCoord::GetCoordValue() const
302 NS_ASSERTION((mUnit
== eStyleUnit_Coord
), "not a coord value");
303 if (mUnit
== eStyleUnit_Coord
) {
309 inline int32_t nsStyleCoord::GetIntValue() const
311 NS_ASSERTION((mUnit
== eStyleUnit_Enumerated
) ||
312 (mUnit
== eStyleUnit_Integer
), "not an int value");
313 if ((mUnit
== eStyleUnit_Enumerated
) ||
314 (mUnit
== eStyleUnit_Integer
)) {
320 inline float nsStyleCoord::GetPercentValue() const
322 NS_ASSERTION(mUnit
== eStyleUnit_Percent
, "not a percent value");
323 if (mUnit
== eStyleUnit_Percent
) {
324 return mValue
.mFloat
;
329 inline float nsStyleCoord::GetFactorValue() const
331 NS_ASSERTION(mUnit
== eStyleUnit_Factor
, "not a factor value");
332 if (mUnit
== eStyleUnit_Factor
) {
333 return mValue
.mFloat
;
338 inline float nsStyleCoord::GetFactorOrPercentValue() const
340 NS_ASSERTION(mUnit
== eStyleUnit_Factor
|| mUnit
== eStyleUnit_Percent
,
341 "not a percent or factor value");
342 if (mUnit
== eStyleUnit_Factor
|| mUnit
== eStyleUnit_Percent
) {
343 return mValue
.mFloat
;
348 inline float nsStyleCoord::GetAngleValue() const
350 NS_ASSERTION(mUnit
>= eStyleUnit_Degree
&&
351 mUnit
<= eStyleUnit_Turn
, "not an angle value");
352 if (mUnit
>= eStyleUnit_Degree
&& mUnit
<= eStyleUnit_Turn
) {
353 return mValue
.mFloat
;
358 inline float nsStyleCoord::GetFlexFractionValue() const
360 NS_ASSERTION(mUnit
== eStyleUnit_FlexFraction
, "not a fr value");
361 if (mUnit
== eStyleUnit_FlexFraction
) {
362 return mValue
.mFloat
;
367 inline nsStyleCoord::Calc
* nsStyleCoord::GetCalcValue() const
369 NS_ASSERTION(IsCalcUnit(), "not a pointer value");
371 return static_cast<Calc
*>(mValue
.mPointer
);
376 /* static */ inline void
377 nsStyleCoord::Reset(nsStyleUnit
& aUnit
, nsStyleUnion
& aValue
)
379 MOZ_ASSERT(aUnit
<= eStyleUnit_MAX
,
380 "calling Reset on uninitialized nsStyleCoord?");
383 case eStyleUnit_Calc
:
384 static_cast<Calc
*>(aValue
.mPointer
)->Release();
387 MOZ_ASSERT(!IsPointerUnit(aUnit
), "check pointer refcounting logic");
390 aUnit
= eStyleUnit_Null
;
394 /* static */ inline void
395 nsStyleCoord::SetValue(nsStyleUnit
& aUnit
,
396 nsStyleUnion
& aValue
,
397 nsStyleUnit aOtherUnit
,
398 const nsStyleUnion
& aOtherValue
)
400 Reset(aUnit
, aValue
);
403 aValue
= aOtherValue
;
406 case eStyleUnit_Calc
:
407 static_cast<Calc
*>(aValue
.mPointer
)->AddRef();
410 MOZ_ASSERT(!IsPointerUnit(aUnit
), "check pointer refcounting logic");
414 /* static */ inline void
415 nsStyleCoord::SetValue(nsStyleUnit
& aUnit
, nsStyleUnion
& aValue
,
416 const nsStyleCoord
& aOther
)
418 SetValue(aUnit
, aValue
, aOther
.mUnit
, aOther
.mValue
);
422 // -------------------------
423 // nsStyleSides inlines
425 inline bool nsStyleSides::operator!=(const nsStyleSides
& aOther
) const
427 return !((*this) == aOther
);
430 inline nsStyleUnit
nsStyleSides::GetUnit(mozilla::css::Side aSide
) const
432 return (nsStyleUnit
)mUnits
[aSide
];
435 inline nsStyleUnit
nsStyleSides::GetLeftUnit() const
437 return GetUnit(NS_SIDE_LEFT
);
440 inline nsStyleUnit
nsStyleSides::GetTopUnit() const
442 return GetUnit(NS_SIDE_TOP
);
445 inline nsStyleUnit
nsStyleSides::GetRightUnit() const
447 return GetUnit(NS_SIDE_RIGHT
);
450 inline nsStyleUnit
nsStyleSides::GetBottomUnit() const
452 return GetUnit(NS_SIDE_BOTTOM
);
455 inline nsStyleCoord
nsStyleSides::Get(mozilla::css::Side aSide
) const
457 return nsStyleCoord(mValues
[aSide
], nsStyleUnit(mUnits
[aSide
]));
460 inline nsStyleCoord
nsStyleSides::GetLeft() const
462 return Get(NS_SIDE_LEFT
);
465 inline nsStyleCoord
nsStyleSides::GetTop() const
467 return Get(NS_SIDE_TOP
);
470 inline nsStyleCoord
nsStyleSides::GetRight() const
472 return Get(NS_SIDE_RIGHT
);
475 inline nsStyleCoord
nsStyleSides::GetBottom() const
477 return Get(NS_SIDE_BOTTOM
);
480 inline void nsStyleSides::Set(mozilla::css::Side aSide
, const nsStyleCoord
& aCoord
)
482 nsStyleCoord::SetValue(mUnits
[aSide
], mValues
[aSide
], aCoord
);
485 inline void nsStyleSides::SetLeft(const nsStyleCoord
& aCoord
)
487 Set(NS_SIDE_LEFT
, aCoord
);
490 inline void nsStyleSides::SetTop(const nsStyleCoord
& aCoord
)
492 Set(NS_SIDE_TOP
, aCoord
);
495 inline void nsStyleSides::SetRight(const nsStyleCoord
& aCoord
)
497 Set(NS_SIDE_RIGHT
, aCoord
);
500 inline void nsStyleSides::SetBottom(const nsStyleCoord
& aCoord
)
502 Set(NS_SIDE_BOTTOM
, aCoord
);
505 // -------------------------
506 // nsStyleCorners inlines
508 inline bool nsStyleCorners::operator!=(const nsStyleCorners
& aOther
) const
510 return !((*this) == aOther
);
513 inline nsStyleUnit
nsStyleCorners::GetUnit(uint8_t aCorner
) const
515 return (nsStyleUnit
)mUnits
[aCorner
];
518 inline nsStyleCoord
nsStyleCorners::Get(uint8_t aCorner
) const
520 return nsStyleCoord(mValues
[aCorner
], nsStyleUnit(mUnits
[aCorner
]));
523 inline void nsStyleCorners::Set(uint8_t aCorner
, const nsStyleCoord
& aCoord
)
525 nsStyleCoord::SetValue(mUnits
[aCorner
], mValues
[aCorner
], aCoord
);
528 #endif /* nsStyleCoord_h___ */