/src/mozilla-central/layout/style/nsStyleCoord.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* representation of length values in computed style data */ |
8 | | |
9 | | #include "mozilla/HashFunctions.h" |
10 | | #include "mozilla/PodOperations.h" |
11 | | |
12 | | // nsStyleCoord.h must not be the first header in a unified source file, |
13 | | // otherwise it may not build with MSVC due to a bug in our STL wrapper. |
14 | | // See bug 1331102. |
15 | | #include "nsStyleCoord.h" |
16 | | |
17 | | using namespace mozilla; |
18 | | |
19 | | nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit) |
20 | | : mUnit(aUnit) |
21 | 0 | { |
22 | 0 | NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit"); |
23 | 0 | if (aUnit >= eStyleUnit_Percent) { |
24 | 0 | mUnit = eStyleUnit_Null; |
25 | 0 | } |
26 | 0 | mValue.mInt = 0; |
27 | 0 | } |
28 | | |
29 | | nsStyleCoord::nsStyleCoord(int32_t aValue, nsStyleUnit aUnit) |
30 | | : mUnit(aUnit) |
31 | 0 | { |
32 | 0 | //if you want to pass in eStyleUnit_Coord, don't. instead, use the |
33 | 0 | //constructor just above this one... MMP |
34 | 0 | NS_ASSERTION((aUnit == eStyleUnit_Enumerated) || |
35 | 0 | (aUnit == eStyleUnit_Integer), "not an int value"); |
36 | 0 | if ((aUnit == eStyleUnit_Enumerated) || |
37 | 0 | (aUnit == eStyleUnit_Integer)) { |
38 | 0 | mValue.mInt = aValue; |
39 | 0 | } |
40 | 0 | else { |
41 | 0 | mUnit = eStyleUnit_Null; |
42 | 0 | mValue.mInt = 0; |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit) |
47 | | : mUnit(aUnit) |
48 | 0 | { |
49 | 0 | if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) { |
50 | 0 | MOZ_ASSERT_UNREACHABLE("not a float value"); |
51 | 0 | mUnit = eStyleUnit_Null; |
52 | 0 | mValue.mInt = 0; |
53 | 0 | } else { |
54 | 0 | mValue.mFloat = aValue; |
55 | 0 | } |
56 | 0 | } |
57 | | |
58 | | bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const |
59 | 0 | { |
60 | 0 | if (mUnit != aOther.mUnit) { |
61 | 0 | return false; |
62 | 0 | } |
63 | 0 | switch (mUnit) { |
64 | 0 | case eStyleUnit_Null: |
65 | 0 | case eStyleUnit_Normal: |
66 | 0 | case eStyleUnit_Auto: |
67 | 0 | case eStyleUnit_None: |
68 | 0 | return true; |
69 | 0 | case eStyleUnit_Percent: |
70 | 0 | case eStyleUnit_Factor: |
71 | 0 | case eStyleUnit_Degree: |
72 | 0 | case eStyleUnit_Grad: |
73 | 0 | case eStyleUnit_Radian: |
74 | 0 | case eStyleUnit_Turn: |
75 | 0 | case eStyleUnit_FlexFraction: |
76 | 0 | return mValue.mFloat == aOther.mValue.mFloat; |
77 | 0 | case eStyleUnit_Coord: |
78 | 0 | case eStyleUnit_Integer: |
79 | 0 | case eStyleUnit_Enumerated: |
80 | 0 | return mValue.mInt == aOther.mValue.mInt; |
81 | 0 | case eStyleUnit_Calc: |
82 | 0 | return *this->GetCalcValue() == *aOther.GetCalcValue(); |
83 | 0 | } |
84 | 0 | MOZ_ASSERT(false, "unexpected unit"); |
85 | 0 | return false; |
86 | 0 | } |
87 | | |
88 | | void nsStyleCoord::Reset() |
89 | 0 | { |
90 | 0 | Reset(mUnit, mValue); |
91 | 0 | } |
92 | | |
93 | | void nsStyleCoord::SetCoordValue(nscoord aValue) |
94 | 0 | { |
95 | 0 | Reset(); |
96 | 0 | mUnit = eStyleUnit_Coord; |
97 | 0 | mValue.mInt = aValue; |
98 | 0 | } |
99 | | |
100 | | void nsStyleCoord::SetIntValue(int32_t aValue, nsStyleUnit aUnit) |
101 | 0 | { |
102 | 0 | NS_ASSERTION((aUnit == eStyleUnit_Enumerated) || |
103 | 0 | (aUnit == eStyleUnit_Integer), "not an int value"); |
104 | 0 | Reset(); |
105 | 0 | if ((aUnit == eStyleUnit_Enumerated) || |
106 | 0 | (aUnit == eStyleUnit_Integer)) { |
107 | 0 | mUnit = aUnit; |
108 | 0 | mValue.mInt = aValue; |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | | void nsStyleCoord::SetPercentValue(float aValue) |
113 | 0 | { |
114 | 0 | Reset(); |
115 | 0 | mUnit = eStyleUnit_Percent; |
116 | 0 | mValue.mFloat = aValue; |
117 | 0 | } |
118 | | |
119 | | void nsStyleCoord::SetFactorValue(float aValue) |
120 | 0 | { |
121 | 0 | Reset(); |
122 | 0 | mUnit = eStyleUnit_Factor; |
123 | 0 | mValue.mFloat = aValue; |
124 | 0 | } |
125 | | |
126 | | void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit) |
127 | 0 | { |
128 | 0 | Reset(); |
129 | 0 | if (aUnit == eStyleUnit_Degree || |
130 | 0 | aUnit == eStyleUnit_Grad || |
131 | 0 | aUnit == eStyleUnit_Radian || |
132 | 0 | aUnit == eStyleUnit_Turn) { |
133 | 0 | mUnit = aUnit; |
134 | 0 | mValue.mFloat = aValue; |
135 | 0 | } else { |
136 | 0 | MOZ_ASSERT_UNREACHABLE("not an angle value"); |
137 | 0 | } |
138 | 0 | } |
139 | | |
140 | | void nsStyleCoord::SetFlexFractionValue(float aValue) |
141 | 0 | { |
142 | 0 | Reset(); |
143 | 0 | mUnit = eStyleUnit_FlexFraction; |
144 | 0 | mValue.mFloat = aValue; |
145 | 0 | } |
146 | | |
147 | | void nsStyleCoord::SetCalcValue(Calc* aValue) |
148 | 0 | { |
149 | 0 | Reset(); |
150 | 0 | mUnit = eStyleUnit_Calc; |
151 | 0 | mValue.mPointer = aValue; |
152 | 0 | aValue->AddRef(); |
153 | 0 | } |
154 | | |
155 | | void nsStyleCoord::SetNormalValue() |
156 | 0 | { |
157 | 0 | Reset(); |
158 | 0 | mUnit = eStyleUnit_Normal; |
159 | 0 | mValue.mInt = 0; |
160 | 0 | } |
161 | | |
162 | | void nsStyleCoord::SetAutoValue() |
163 | 0 | { |
164 | 0 | Reset(); |
165 | 0 | mUnit = eStyleUnit_Auto; |
166 | 0 | mValue.mInt = 0; |
167 | 0 | } |
168 | | |
169 | | void nsStyleCoord::SetNoneValue() |
170 | 0 | { |
171 | 0 | Reset(); |
172 | 0 | mUnit = eStyleUnit_None; |
173 | 0 | mValue.mInt = 0; |
174 | 0 | } |
175 | | |
176 | | // accessors that are not inlined |
177 | | |
178 | | double |
179 | | nsStyleCoord::GetAngleValueInDegrees() const |
180 | 0 | { |
181 | 0 | return GetAngleValueInRadians() * (180.0 / M_PI); |
182 | 0 | } |
183 | | |
184 | | double |
185 | | nsStyleCoord::GetAngleValueInRadians() const |
186 | 0 | { |
187 | 0 | double angle = mValue.mFloat; |
188 | 0 |
|
189 | 0 | switch (GetUnit()) { |
190 | 0 | case eStyleUnit_Radian: return angle; |
191 | 0 | case eStyleUnit_Turn: return angle * 2 * M_PI; |
192 | 0 | case eStyleUnit_Degree: return angle * M_PI / 180.0; |
193 | 0 | case eStyleUnit_Grad: return angle * M_PI / 200.0; |
194 | 0 |
|
195 | 0 | default: |
196 | 0 | MOZ_ASSERT_UNREACHABLE("unrecognized angular unit"); |
197 | 0 | return 0.0; |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | | nscoord |
202 | | nsStyleCoord::ComputeComputedCalc(nscoord aPercentageBasis) const |
203 | 0 | { |
204 | 0 | Calc* calc = GetCalcValue(); |
205 | 0 | return calc->mLength + |
206 | 0 | NSToCoordFloorClamped(aPercentageBasis * calc->mPercent); |
207 | 0 | } |
208 | | |
209 | | nscoord |
210 | | nsStyleCoord::ComputeCoordPercentCalc(nscoord aPercentageBasis) const |
211 | 0 | { |
212 | 0 | switch (GetUnit()) { |
213 | 0 | case eStyleUnit_Coord: |
214 | 0 | return GetCoordValue(); |
215 | 0 | case eStyleUnit_Percent: |
216 | 0 | return NSToCoordFloorClamped(aPercentageBasis * GetPercentValue()); |
217 | 0 | case eStyleUnit_Calc: |
218 | 0 | return ComputeComputedCalc(aPercentageBasis); |
219 | 0 | default: |
220 | 0 | MOZ_ASSERT_UNREACHABLE("Unexpected unit!"); |
221 | 0 | return 0; |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | | nsStyleSides::nsStyleSides() |
226 | 0 | { |
227 | 0 | NS_FOR_CSS_SIDES(i) { |
228 | 0 | mUnits[i] = eStyleUnit_Null; |
229 | 0 | } |
230 | 0 | mozilla::PodArrayZero(mValues); |
231 | 0 | } |
232 | | |
233 | | nsStyleSides::nsStyleSides(const nsStyleSides& aOther) |
234 | 0 | { |
235 | 0 | NS_FOR_CSS_SIDES(i) { |
236 | 0 | mUnits[i] = eStyleUnit_Null; |
237 | 0 | } |
238 | 0 | *this = aOther; |
239 | 0 | } |
240 | | |
241 | | nsStyleSides::~nsStyleSides() |
242 | 0 | { |
243 | 0 | Reset(); |
244 | 0 | } |
245 | | |
246 | | nsStyleSides& |
247 | | nsStyleSides::operator=(const nsStyleSides& aCopy) |
248 | 0 | { |
249 | 0 | if (this != &aCopy) { |
250 | 0 | NS_FOR_CSS_SIDES(i) { |
251 | 0 | nsStyleCoord::SetValue(mUnits[i], mValues[i], |
252 | 0 | aCopy.mUnits[i], aCopy.mValues[i]); |
253 | 0 | } |
254 | 0 | } |
255 | 0 | return *this; |
256 | 0 | } |
257 | | |
258 | | bool nsStyleSides::operator==(const nsStyleSides& aOther) const |
259 | 0 | { |
260 | 0 | NS_FOR_CSS_SIDES(i) { |
261 | 0 | if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) != |
262 | 0 | nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) { |
263 | 0 | return false; |
264 | 0 | } |
265 | 0 | } |
266 | 0 | return true; |
267 | 0 | } |
268 | | |
269 | | void nsStyleSides::Reset() |
270 | 0 | { |
271 | 0 | NS_FOR_CSS_SIDES(i) { |
272 | 0 | nsStyleCoord::Reset(mUnits[i], mValues[i]); |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | | nsStyleCorners::nsStyleCorners() |
277 | 0 | { |
278 | 0 | NS_FOR_CSS_HALF_CORNERS(i) { |
279 | 0 | mUnits[i] = eStyleUnit_Null; |
280 | 0 | } |
281 | 0 | mozilla::PodArrayZero(mValues); |
282 | 0 | } |
283 | | |
284 | | nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther) |
285 | 0 | { |
286 | 0 | NS_FOR_CSS_HALF_CORNERS(i) { |
287 | 0 | mUnits[i] = eStyleUnit_Null; |
288 | 0 | } |
289 | 0 | *this = aOther; |
290 | 0 | } |
291 | | |
292 | | nsStyleCorners::~nsStyleCorners() |
293 | 0 | { |
294 | 0 | Reset(); |
295 | 0 | } |
296 | | |
297 | | nsStyleCorners& |
298 | | nsStyleCorners::operator=(const nsStyleCorners& aCopy) |
299 | 0 | { |
300 | 0 | if (this != &aCopy) { |
301 | 0 | NS_FOR_CSS_HALF_CORNERS(i) { |
302 | 0 | nsStyleCoord::SetValue(mUnits[i], mValues[i], |
303 | 0 | aCopy.mUnits[i], aCopy.mValues[i]); |
304 | 0 | } |
305 | 0 | } |
306 | 0 | return *this; |
307 | 0 | } |
308 | | |
309 | | bool |
310 | | nsStyleCorners::operator==(const nsStyleCorners& aOther) const |
311 | 0 | { |
312 | 0 | NS_FOR_CSS_HALF_CORNERS(i) { |
313 | 0 | if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) != |
314 | 0 | nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) { |
315 | 0 | return false; |
316 | 0 | } |
317 | 0 | } |
318 | 0 | return true; |
319 | 0 | } |
320 | | |
321 | | void nsStyleCorners::Reset() |
322 | 0 | { |
323 | 0 | NS_FOR_CSS_HALF_CORNERS(i) { |
324 | 0 | nsStyleCoord::Reset(mUnits[i], mValues[i]); |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | | // Validation of SideIsVertical. |
329 | | #define CASE(side, result) \ |
330 | | static_assert(SideIsVertical(side) == result, \ |
331 | | "SideIsVertical is wrong") |
332 | | CASE(eSideTop, false); |
333 | | CASE(eSideRight, true); |
334 | | CASE(eSideBottom, false); |
335 | | CASE(eSideLeft, true); |
336 | | #undef CASE |
337 | | |
338 | | // Validation of HalfCornerIsX. |
339 | | #define CASE(corner, result) \ |
340 | | static_assert(HalfCornerIsX(corner) == result, \ |
341 | | "HalfCornerIsX is wrong") |
342 | | CASE(eCornerTopLeftX, true); |
343 | | CASE(eCornerTopLeftY, false); |
344 | | CASE(eCornerTopRightX, true); |
345 | | CASE(eCornerTopRightY, false); |
346 | | CASE(eCornerBottomRightX, true); |
347 | | CASE(eCornerBottomRightY, false); |
348 | | CASE(eCornerBottomLeftX, true); |
349 | | CASE(eCornerBottomLeftY, false); |
350 | | #undef CASE |
351 | | |
352 | | // Validation of HalfToFullCorner. |
353 | | #define CASE(corner, result) \ |
354 | | static_assert(HalfToFullCorner(corner) == result, \ |
355 | | "HalfToFullCorner is wrong") |
356 | | CASE(eCornerTopLeftX, eCornerTopLeft); |
357 | | CASE(eCornerTopLeftY, eCornerTopLeft); |
358 | | CASE(eCornerTopRightX, eCornerTopRight); |
359 | | CASE(eCornerTopRightY, eCornerTopRight); |
360 | | CASE(eCornerBottomRightX, eCornerBottomRight); |
361 | | CASE(eCornerBottomRightY, eCornerBottomRight); |
362 | | CASE(eCornerBottomLeftX, eCornerBottomLeft); |
363 | | CASE(eCornerBottomLeftY, eCornerBottomLeft); |
364 | | #undef CASE |
365 | | |
366 | | // Validation of FullToHalfCorner. |
367 | | #define CASE(corner, vert, result) \ |
368 | | static_assert(FullToHalfCorner(corner, vert) == result, \ |
369 | | "FullToHalfCorner is wrong") |
370 | | CASE(eCornerTopLeft, false, eCornerTopLeftX); |
371 | | CASE(eCornerTopLeft, true, eCornerTopLeftY); |
372 | | CASE(eCornerTopRight, false, eCornerTopRightX); |
373 | | CASE(eCornerTopRight, true, eCornerTopRightY); |
374 | | CASE(eCornerBottomRight, false, eCornerBottomRightX); |
375 | | CASE(eCornerBottomRight, true, eCornerBottomRightY); |
376 | | CASE(eCornerBottomLeft, false, eCornerBottomLeftX); |
377 | | CASE(eCornerBottomLeft, true, eCornerBottomLeftY); |
378 | | #undef CASE |
379 | | |
380 | | // Validation of SideToFullCorner. |
381 | | #define CASE(side, second, result) \ |
382 | | static_assert(SideToFullCorner(side, second) == result, \ |
383 | | "SideToFullCorner is wrong") |
384 | | CASE(eSideTop, false, eCornerTopLeft); |
385 | | CASE(eSideTop, true, eCornerTopRight); |
386 | | |
387 | | CASE(eSideRight, false, eCornerTopRight); |
388 | | CASE(eSideRight, true, eCornerBottomRight); |
389 | | |
390 | | CASE(eSideBottom, false, eCornerBottomRight); |
391 | | CASE(eSideBottom, true, eCornerBottomLeft); |
392 | | |
393 | | CASE(eSideLeft, false, eCornerBottomLeft); |
394 | | CASE(eSideLeft, true, eCornerTopLeft); |
395 | | #undef CASE |
396 | | |
397 | | // Validation of SideToHalfCorner. |
398 | | #define CASE(side, second, parallel, result) \ |
399 | | static_assert(SideToHalfCorner(side, second, parallel) == result, \ |
400 | | "SideToHalfCorner is wrong") |
401 | | CASE(eSideTop, false, true, eCornerTopLeftX); |
402 | | CASE(eSideTop, false, false, eCornerTopLeftY); |
403 | | CASE(eSideTop, true, true, eCornerTopRightX); |
404 | | CASE(eSideTop, true, false, eCornerTopRightY); |
405 | | |
406 | | CASE(eSideRight, false, false, eCornerTopRightX); |
407 | | CASE(eSideRight, false, true, eCornerTopRightY); |
408 | | CASE(eSideRight, true, false, eCornerBottomRightX); |
409 | | CASE(eSideRight, true, true, eCornerBottomRightY); |
410 | | |
411 | | CASE(eSideBottom, false, true, eCornerBottomRightX); |
412 | | CASE(eSideBottom, false, false, eCornerBottomRightY); |
413 | | CASE(eSideBottom, true, true, eCornerBottomLeftX); |
414 | | CASE(eSideBottom, true, false, eCornerBottomLeftY); |
415 | | |
416 | | CASE(eSideLeft, false, false, eCornerBottomLeftX); |
417 | | CASE(eSideLeft, false, true, eCornerBottomLeftY); |
418 | | CASE(eSideLeft, true, false, eCornerTopLeftX); |
419 | | CASE(eSideLeft, true, true, eCornerTopLeftY); |
420 | | #undef CASE |