Bumping manifests a=b2g-bump
[gecko.git] / layout / style / nsStyleCoord.cpp
blobf014e57ae6bbaca3206b510a54ad3e7a7008314e
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)
13 : mUnit(aUnit)
15 NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit");
16 if (aUnit >= eStyleUnit_Percent) {
17 mUnit = eStyleUnit_Null;
19 mValue.mInt = 0;
22 nsStyleCoord::nsStyleCoord(int32_t aValue, nsStyleUnit aUnit)
23 : mUnit(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)) {
31 mValue.mInt = aValue;
33 else {
34 mUnit = eStyleUnit_Null;
35 mValue.mInt = 0;
39 nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit)
40 : mUnit(aUnit)
42 if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) {
43 NS_NOTREACHED("not a float value");
44 mUnit = eStyleUnit_Null;
45 mValue.mInt = 0;
46 } else {
47 mValue.mFloat = aValue;
51 bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const
53 if (mUnit != aOther.mUnit) {
54 return false;
56 switch (mUnit) {
57 case eStyleUnit_Null:
58 case eStyleUnit_Normal:
59 case eStyleUnit_Auto:
60 case eStyleUnit_None:
61 return true;
62 case eStyleUnit_Percent:
63 case eStyleUnit_Factor:
64 case eStyleUnit_Degree:
65 case eStyleUnit_Grad:
66 case eStyleUnit_Radian:
67 case eStyleUnit_Turn:
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;
74 case eStyleUnit_Calc:
75 return *this->GetCalcValue() == *aOther.GetCalcValue();
77 NS_ABORT_IF_FALSE(false, "unexpected unit");
78 return false;
81 uint32_t nsStyleCoord::HashValue(uint32_t aHash = 0) const
83 aHash = mozilla::AddToHash(aHash, mUnit);
85 switch (mUnit) {
86 case eStyleUnit_Null:
87 case eStyleUnit_Normal:
88 case eStyleUnit_Auto:
89 case eStyleUnit_None:
90 return mozilla::AddToHash(aHash, true);
91 case eStyleUnit_Percent:
92 case eStyleUnit_Factor:
93 case eStyleUnit_Degree:
94 case eStyleUnit_Grad:
95 case eStyleUnit_Radian:
96 case eStyleUnit_Turn:
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);
106 if (HasPercent()) {
107 return mozilla::AddToHash(aHash, calcValue->mPercent);
109 return aHash;
111 NS_ABORT_IF_FALSE(false, "unexpected unit");
112 return aHash;
115 void nsStyleCoord::Reset()
117 Reset(mUnit, mValue);
120 void nsStyleCoord::SetCoordValue(nscoord aValue)
122 Reset();
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");
131 Reset();
132 if ((aUnit == eStyleUnit_Enumerated) ||
133 (aUnit == eStyleUnit_Integer)) {
134 mUnit = aUnit;
135 mValue.mInt = aValue;
139 void nsStyleCoord::SetPercentValue(float aValue)
141 Reset();
142 mUnit = eStyleUnit_Percent;
143 mValue.mFloat = aValue;
146 void nsStyleCoord::SetFactorValue(float aValue)
148 Reset();
149 mUnit = eStyleUnit_Factor;
150 mValue.mFloat = aValue;
153 void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit)
155 Reset();
156 if (aUnit == eStyleUnit_Degree ||
157 aUnit == eStyleUnit_Grad ||
158 aUnit == eStyleUnit_Radian ||
159 aUnit == eStyleUnit_Turn) {
160 mUnit = aUnit;
161 mValue.mFloat = aValue;
162 } else {
163 NS_NOTREACHED("not an angle value");
167 void nsStyleCoord::SetFlexFractionValue(float aValue)
169 Reset();
170 mUnit = eStyleUnit_FlexFraction;
171 mValue.mFloat = aValue;
174 void nsStyleCoord::SetCalcValue(Calc* aValue)
176 Reset();
177 mUnit = eStyleUnit_Calc;
178 mValue.mPointer = aValue;
179 aValue->AddRef();
182 void nsStyleCoord::SetNormalValue()
184 Reset();
185 mUnit = eStyleUnit_Normal;
186 mValue.mInt = 0;
189 void nsStyleCoord::SetAutoValue()
191 Reset();
192 mUnit = eStyleUnit_Auto;
193 mValue.mInt = 0;
196 void nsStyleCoord::SetNoneValue()
198 Reset();
199 mUnit = eStyleUnit_None;
200 mValue.mInt = 0;
203 // accessors that are not inlined
205 double
206 nsStyleCoord::GetAngleValueInDegrees() const
208 return GetAngleValueInRadians() * (180.0 / M_PI);
211 double
212 nsStyleCoord::GetAngleValueInRadians() const
214 double angle = mValue.mFloat;
216 switch (GetUnit()) {
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;
222 default:
223 NS_NOTREACHED("unrecognized angular unit");
224 return 0.0;
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;
241 *this = aOther;
244 nsStyleSides::~nsStyleSides()
246 Reset();
249 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]);
258 return *this;
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])) {
266 return false;
269 return true;
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;
292 *this = aOther;
295 nsStyleCorners::~nsStyleCorners()
297 Reset();
300 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]);
309 return *this;
312 bool
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])) {
318 return false;
321 return true;
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);
339 #undef CASE
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);
352 #undef CASE
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);
366 #undef CASE
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);
380 #undef CASE
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);
397 #undef CASE
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);
421 #undef CASE