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 #include "nsStyleCoord.h"
9 #include "mozilla/HashFunctions.h"
10 #include "mozilla/PodOperations.h"
12 nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit
)
15 NS_ASSERTION(aUnit
< eStyleUnit_Percent
, "not a valueless unit");
16 if (aUnit
>= eStyleUnit_Percent
) {
17 mUnit
= eStyleUnit_Null
;
22 nsStyleCoord::nsStyleCoord(int32_t aValue
, nsStyleUnit aUnit
)
25 //if you want to pass in eStyleUnit_Coord, don't. instead, use the
26 //constructor just above this one... MMP
27 NS_ASSERTION((aUnit
== eStyleUnit_Enumerated
) ||
28 (aUnit
== eStyleUnit_Integer
), "not an int value");
29 if ((aUnit
== eStyleUnit_Enumerated
) ||
30 (aUnit
== eStyleUnit_Integer
)) {
34 mUnit
= eStyleUnit_Null
;
39 nsStyleCoord::nsStyleCoord(float aValue
, nsStyleUnit aUnit
)
42 if (aUnit
< eStyleUnit_Percent
|| aUnit
>= eStyleUnit_Coord
) {
43 NS_NOTREACHED("not a float value");
44 mUnit
= eStyleUnit_Null
;
47 mValue
.mFloat
= aValue
;
51 bool nsStyleCoord::operator==(const nsStyleCoord
& aOther
) const
53 if (mUnit
!= aOther
.mUnit
) {
58 case eStyleUnit_Normal
:
62 case eStyleUnit_Percent
:
63 case eStyleUnit_Factor
:
64 case eStyleUnit_Degree
:
66 case eStyleUnit_Radian
:
68 case eStyleUnit_FlexFraction
:
69 return mValue
.mFloat
== aOther
.mValue
.mFloat
;
70 case eStyleUnit_Coord
:
71 case eStyleUnit_Integer
:
72 case eStyleUnit_Enumerated
:
73 return mValue
.mInt
== aOther
.mValue
.mInt
;
75 return *this->GetCalcValue() == *aOther
.GetCalcValue();
77 NS_ABORT_IF_FALSE(false, "unexpected unit");
81 uint32_t nsStyleCoord::HashValue(uint32_t aHash
= 0) const
83 aHash
= mozilla::AddToHash(aHash
, mUnit
);
87 case eStyleUnit_Normal
:
90 return mozilla::AddToHash(aHash
, true);
91 case eStyleUnit_Percent
:
92 case eStyleUnit_Factor
:
93 case eStyleUnit_Degree
:
95 case eStyleUnit_Radian
:
97 case eStyleUnit_FlexFraction
:
98 return mozilla::AddToHash(aHash
, mValue
.mFloat
);
99 case eStyleUnit_Coord
:
100 case eStyleUnit_Integer
:
101 case eStyleUnit_Enumerated
:
102 return mozilla::AddToHash(aHash
, mValue
.mInt
);
103 case eStyleUnit_Calc
:
104 Calc
* calcValue
= GetCalcValue();
105 aHash
= mozilla::AddToHash(aHash
, calcValue
->mLength
);
107 return mozilla::AddToHash(aHash
, calcValue
->mPercent
);
111 NS_ABORT_IF_FALSE(false, "unexpected unit");
115 void nsStyleCoord::Reset()
117 Reset(mUnit
, mValue
);
120 void nsStyleCoord::SetCoordValue(nscoord aValue
)
123 mUnit
= eStyleUnit_Coord
;
124 mValue
.mInt
= aValue
;
127 void nsStyleCoord::SetIntValue(int32_t aValue
, nsStyleUnit aUnit
)
129 NS_ASSERTION((aUnit
== eStyleUnit_Enumerated
) ||
130 (aUnit
== eStyleUnit_Integer
), "not an int value");
132 if ((aUnit
== eStyleUnit_Enumerated
) ||
133 (aUnit
== eStyleUnit_Integer
)) {
135 mValue
.mInt
= aValue
;
139 void nsStyleCoord::SetPercentValue(float aValue
)
142 mUnit
= eStyleUnit_Percent
;
143 mValue
.mFloat
= aValue
;
146 void nsStyleCoord::SetFactorValue(float aValue
)
149 mUnit
= eStyleUnit_Factor
;
150 mValue
.mFloat
= aValue
;
153 void nsStyleCoord::SetAngleValue(float aValue
, nsStyleUnit aUnit
)
156 if (aUnit
== eStyleUnit_Degree
||
157 aUnit
== eStyleUnit_Grad
||
158 aUnit
== eStyleUnit_Radian
||
159 aUnit
== eStyleUnit_Turn
) {
161 mValue
.mFloat
= aValue
;
163 NS_NOTREACHED("not an angle value");
167 void nsStyleCoord::SetFlexFractionValue(float aValue
)
170 mUnit
= eStyleUnit_FlexFraction
;
171 mValue
.mFloat
= aValue
;
174 void nsStyleCoord::SetCalcValue(Calc
* aValue
)
177 mUnit
= eStyleUnit_Calc
;
178 mValue
.mPointer
= aValue
;
182 void nsStyleCoord::SetNormalValue()
185 mUnit
= eStyleUnit_Normal
;
189 void nsStyleCoord::SetAutoValue()
192 mUnit
= eStyleUnit_Auto
;
196 void nsStyleCoord::SetNoneValue()
199 mUnit
= eStyleUnit_None
;
203 // accessors that are not inlined
206 nsStyleCoord::GetAngleValueInDegrees() const
208 return GetAngleValueInRadians() * (180.0 / M_PI
);
212 nsStyleCoord::GetAngleValueInRadians() const
214 double angle
= mValue
.mFloat
;
217 case eStyleUnit_Radian
: return angle
;
218 case eStyleUnit_Turn
: return angle
* 2 * M_PI
;
219 case eStyleUnit_Degree
: return angle
* M_PI
/ 180.0;
220 case eStyleUnit_Grad
: return angle
* M_PI
/ 200.0;
223 NS_NOTREACHED("unrecognized angular unit");
228 nsStyleSides::nsStyleSides()
230 NS_FOR_CSS_SIDES(i
) {
231 mUnits
[i
] = eStyleUnit_Null
;
233 mozilla::PodArrayZero(mValues
);
236 nsStyleSides::nsStyleSides(const nsStyleSides
& aOther
)
238 NS_FOR_CSS_SIDES(i
) {
239 mUnits
[i
] = eStyleUnit_Null
;
244 nsStyleSides::~nsStyleSides()
250 nsStyleSides::operator=(const nsStyleSides
& aCopy
)
252 if (this != &aCopy
) {
253 NS_FOR_CSS_SIDES(i
) {
254 nsStyleCoord::SetValue(mUnits
[i
], mValues
[i
],
255 aCopy
.mUnits
[i
], aCopy
.mValues
[i
]);
261 bool nsStyleSides::operator==(const nsStyleSides
& aOther
) const
263 NS_FOR_CSS_SIDES(i
) {
264 if (nsStyleCoord(mValues
[i
], (nsStyleUnit
)mUnits
[i
]) !=
265 nsStyleCoord(aOther
.mValues
[i
], (nsStyleUnit
)aOther
.mUnits
[i
])) {
272 void nsStyleSides::Reset()
274 NS_FOR_CSS_SIDES(i
) {
275 nsStyleCoord::Reset(mUnits
[i
], mValues
[i
]);
279 nsStyleCorners::nsStyleCorners()
281 NS_FOR_CSS_HALF_CORNERS(i
) {
282 mUnits
[i
] = eStyleUnit_Null
;
284 mozilla::PodArrayZero(mValues
);
287 nsStyleCorners::nsStyleCorners(const nsStyleCorners
& aOther
)
289 NS_FOR_CSS_HALF_CORNERS(i
) {
290 mUnits
[i
] = eStyleUnit_Null
;
295 nsStyleCorners::~nsStyleCorners()
301 nsStyleCorners::operator=(const nsStyleCorners
& aCopy
)
303 if (this != &aCopy
) {
304 NS_FOR_CSS_HALF_CORNERS(i
) {
305 nsStyleCoord::SetValue(mUnits
[i
], mValues
[i
],
306 aCopy
.mUnits
[i
], aCopy
.mValues
[i
]);
313 nsStyleCorners::operator==(const nsStyleCorners
& aOther
) const
315 NS_FOR_CSS_HALF_CORNERS(i
) {
316 if (nsStyleCoord(mValues
[i
], (nsStyleUnit
)mUnits
[i
]) !=
317 nsStyleCoord(aOther
.mValues
[i
], (nsStyleUnit
)aOther
.mUnits
[i
])) {
324 void nsStyleCorners::Reset()
326 NS_FOR_CSS_HALF_CORNERS(i
) {
327 nsStyleCoord::Reset(mUnits
[i
], mValues
[i
]);
331 // Validation of NS_SIDE_IS_VERTICAL and NS_HALF_CORNER_IS_X.
332 #define CASE(side, result) \
333 static_assert(NS_SIDE_IS_VERTICAL(side) == result, \
334 "NS_SIDE_IS_VERTICAL is wrong")
335 CASE(NS_SIDE_TOP
, false);
336 CASE(NS_SIDE_RIGHT
, true);
337 CASE(NS_SIDE_BOTTOM
, false);
338 CASE(NS_SIDE_LEFT
, true);
341 #define CASE(corner, result) \
342 static_assert(NS_HALF_CORNER_IS_X(corner) == result, \
343 "NS_HALF_CORNER_IS_X is wrong")
344 CASE(NS_CORNER_TOP_LEFT_X
, true);
345 CASE(NS_CORNER_TOP_LEFT_Y
, false);
346 CASE(NS_CORNER_TOP_RIGHT_X
, true);
347 CASE(NS_CORNER_TOP_RIGHT_Y
, false);
348 CASE(NS_CORNER_BOTTOM_RIGHT_X
, true);
349 CASE(NS_CORNER_BOTTOM_RIGHT_Y
, false);
350 CASE(NS_CORNER_BOTTOM_LEFT_X
, true);
351 CASE(NS_CORNER_BOTTOM_LEFT_Y
, false);
354 // Validation of NS_HALF_TO_FULL_CORNER.
355 #define CASE(corner, result) \
356 static_assert(NS_HALF_TO_FULL_CORNER(corner) == result, \
357 "NS_HALF_TO_FULL_CORNER is wrong")
358 CASE(NS_CORNER_TOP_LEFT_X
, NS_CORNER_TOP_LEFT
);
359 CASE(NS_CORNER_TOP_LEFT_Y
, NS_CORNER_TOP_LEFT
);
360 CASE(NS_CORNER_TOP_RIGHT_X
, NS_CORNER_TOP_RIGHT
);
361 CASE(NS_CORNER_TOP_RIGHT_Y
, NS_CORNER_TOP_RIGHT
);
362 CASE(NS_CORNER_BOTTOM_RIGHT_X
, NS_CORNER_BOTTOM_RIGHT
);
363 CASE(NS_CORNER_BOTTOM_RIGHT_Y
, NS_CORNER_BOTTOM_RIGHT
);
364 CASE(NS_CORNER_BOTTOM_LEFT_X
, NS_CORNER_BOTTOM_LEFT
);
365 CASE(NS_CORNER_BOTTOM_LEFT_Y
, NS_CORNER_BOTTOM_LEFT
);
368 // Validation of NS_FULL_TO_HALF_CORNER.
369 #define CASE(corner, vert, result) \
370 static_assert(NS_FULL_TO_HALF_CORNER(corner, vert) == result, \
371 "NS_FULL_TO_HALF_CORNER is wrong")
372 CASE(NS_CORNER_TOP_LEFT
, false, NS_CORNER_TOP_LEFT_X
);
373 CASE(NS_CORNER_TOP_LEFT
, true, NS_CORNER_TOP_LEFT_Y
);
374 CASE(NS_CORNER_TOP_RIGHT
, false, NS_CORNER_TOP_RIGHT_X
);
375 CASE(NS_CORNER_TOP_RIGHT
, true, NS_CORNER_TOP_RIGHT_Y
);
376 CASE(NS_CORNER_BOTTOM_RIGHT
, false, NS_CORNER_BOTTOM_RIGHT_X
);
377 CASE(NS_CORNER_BOTTOM_RIGHT
, true, NS_CORNER_BOTTOM_RIGHT_Y
);
378 CASE(NS_CORNER_BOTTOM_LEFT
, false, NS_CORNER_BOTTOM_LEFT_X
);
379 CASE(NS_CORNER_BOTTOM_LEFT
, true, NS_CORNER_BOTTOM_LEFT_Y
);
382 // Validation of NS_SIDE_TO_{FULL,HALF}_CORNER.
383 #define CASE(side, second, result) \
384 static_assert(NS_SIDE_TO_FULL_CORNER(side, second) == result, \
385 "NS_SIDE_TO_FULL_CORNER is wrong")
386 CASE(NS_SIDE_TOP
, false, NS_CORNER_TOP_LEFT
);
387 CASE(NS_SIDE_TOP
, true, NS_CORNER_TOP_RIGHT
);
389 CASE(NS_SIDE_RIGHT
, false, NS_CORNER_TOP_RIGHT
);
390 CASE(NS_SIDE_RIGHT
, true, NS_CORNER_BOTTOM_RIGHT
);
392 CASE(NS_SIDE_BOTTOM
, false, NS_CORNER_BOTTOM_RIGHT
);
393 CASE(NS_SIDE_BOTTOM
, true, NS_CORNER_BOTTOM_LEFT
);
395 CASE(NS_SIDE_LEFT
, false, NS_CORNER_BOTTOM_LEFT
);
396 CASE(NS_SIDE_LEFT
, true, NS_CORNER_TOP_LEFT
);
399 #define CASE(side, second, parallel, result) \
400 static_assert(NS_SIDE_TO_HALF_CORNER(side, second, parallel) == result, \
401 "NS_SIDE_TO_HALF_CORNER is wrong")
402 CASE(NS_SIDE_TOP
, false, true, NS_CORNER_TOP_LEFT_X
);
403 CASE(NS_SIDE_TOP
, false, false, NS_CORNER_TOP_LEFT_Y
);
404 CASE(NS_SIDE_TOP
, true, true, NS_CORNER_TOP_RIGHT_X
);
405 CASE(NS_SIDE_TOP
, true, false, NS_CORNER_TOP_RIGHT_Y
);
407 CASE(NS_SIDE_RIGHT
, false, false, NS_CORNER_TOP_RIGHT_X
);
408 CASE(NS_SIDE_RIGHT
, false, true, NS_CORNER_TOP_RIGHT_Y
);
409 CASE(NS_SIDE_RIGHT
, true, false, NS_CORNER_BOTTOM_RIGHT_X
);
410 CASE(NS_SIDE_RIGHT
, true, true, NS_CORNER_BOTTOM_RIGHT_Y
);
412 CASE(NS_SIDE_BOTTOM
, false, true, NS_CORNER_BOTTOM_RIGHT_X
);
413 CASE(NS_SIDE_BOTTOM
, false, false, NS_CORNER_BOTTOM_RIGHT_Y
);
414 CASE(NS_SIDE_BOTTOM
, true, true, NS_CORNER_BOTTOM_LEFT_X
);
415 CASE(NS_SIDE_BOTTOM
, true, false, NS_CORNER_BOTTOM_LEFT_Y
);
417 CASE(NS_SIDE_LEFT
, false, false, NS_CORNER_BOTTOM_LEFT_X
);
418 CASE(NS_SIDE_LEFT
, false, true, NS_CORNER_BOTTOM_LEFT_Y
);
419 CASE(NS_SIDE_LEFT
, true, false, NS_CORNER_TOP_LEFT_X
);
420 CASE(NS_SIDE_LEFT
, true, true, NS_CORNER_TOP_LEFT_Y
);