1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /* representation of length values in computed style data */
39 :
40 : #ifndef nsStyleCoord_h___
41 : #define nsStyleCoord_h___
42 :
43 : #include "nscore.h"
44 : #include "nsCoord.h"
45 : #include "nsCRT.h"
46 : #include "nsStyleConsts.h"
47 : class nsString;
48 : class nsStyleContext;
49 :
50 : enum nsStyleUnit {
51 : eStyleUnit_Null = 0, // (no value) value is not specified
52 : eStyleUnit_Normal = 1, // (no value)
53 : eStyleUnit_Auto = 2, // (no value)
54 : eStyleUnit_None = 3, // (no value)
55 : eStyleUnit_Percent = 10, // (float) 1.0 == 100%
56 : eStyleUnit_Factor = 11, // (float) a multiplier
57 : eStyleUnit_Degree = 12, // (float) angle in degrees
58 : eStyleUnit_Grad = 13, // (float) angle in grads
59 : eStyleUnit_Radian = 14, // (float) angle in radians
60 : eStyleUnit_Turn = 15, // (float) angle in turns
61 : eStyleUnit_Coord = 20, // (nscoord) value is twips
62 : eStyleUnit_Integer = 30, // (int) value is simple integer
63 : eStyleUnit_Enumerated = 32, // (int) value has enumerated meaning
64 :
65 : // The following are allocated types. They are weak pointers to
66 : // values allocated by nsStyleContext::Alloc.
67 : eStyleUnit_Calc = 40 // (Calc*) calc() toplevel; always present
68 : // to distinguish 50% from calc(50%), etc.
69 : };
70 :
71 : typedef union {
72 : PRInt32 mInt; // nscoord is a PRInt32 for now
73 : float mFloat;
74 : // An mPointer is a weak pointer to a value that is guaranteed to
75 : // outlive the nsStyleCoord. In the case of nsStyleCoord::Calc*, it
76 : // is a pointer owned by the style context, allocated through
77 : // nsStyleContext::Alloc (and, therefore, is never stored in the rule
78 : // tree).
79 : void* mPointer;
80 : } nsStyleUnion;
81 :
82 : /**
83 : * Class that hold a single size specification used by the style
84 : * system. The size specification consists of two parts -- a number
85 : * and a unit. The number is an integer, a floating point value, an
86 : * nscoord, or undefined, and the unit is an nsStyleUnit. Checking
87 : * the unit is a must before asking for the value in any particular
88 : * form.
89 : */
90 : class nsStyleCoord {
91 : public:
92 : struct Calc {
93 : // Every calc() expression evaluates to a length plus a percentage.
94 : nscoord mLength;
95 : float mPercent;
96 : bool mHasPercent; // whether there was any % syntax, even if 0
97 :
98 0 : bool operator==(const Calc& aOther) const {
99 : return mLength == aOther.mLength &&
100 : mPercent == aOther.mPercent &&
101 0 : mHasPercent == aOther.mHasPercent;
102 : }
103 : bool operator!=(const Calc& aOther) const { return !(*this == aOther); }
104 : };
105 :
106 : nsStyleCoord(nsStyleUnit aUnit = eStyleUnit_Null);
107 : enum CoordConstructorType { CoordConstructor };
108 : inline nsStyleCoord(nscoord aValue, CoordConstructorType);
109 : nsStyleCoord(PRInt32 aValue, nsStyleUnit aUnit);
110 : nsStyleCoord(float aValue, nsStyleUnit aUnit);
111 : inline nsStyleCoord(const nsStyleCoord& aCopy);
112 : inline nsStyleCoord(const nsStyleUnion& aValue, nsStyleUnit aUnit);
113 :
114 0 : nsStyleCoord& operator=(const nsStyleCoord& aOther)
115 : {
116 0 : mUnit = aOther.mUnit;
117 0 : mValue = aOther.mValue;
118 0 : return *this;
119 : }
120 : bool operator==(const nsStyleCoord& aOther) const;
121 : bool operator!=(const nsStyleCoord& aOther) const;
122 :
123 0 : nsStyleUnit GetUnit() const {
124 0 : NS_ASSERTION(mUnit != eStyleUnit_Null, "reading uninitialized value");
125 0 : return mUnit;
126 : }
127 :
128 0 : bool IsAngleValue() const {
129 0 : return eStyleUnit_Degree <= mUnit && mUnit <= eStyleUnit_Turn;
130 : }
131 :
132 0 : bool IsCalcUnit() const {
133 0 : return eStyleUnit_Calc == mUnit;
134 : }
135 :
136 0 : bool IsPointerValue() const {
137 0 : return IsCalcUnit();
138 : }
139 :
140 0 : bool IsCoordPercentCalcUnit() const {
141 : return mUnit == eStyleUnit_Coord ||
142 : mUnit == eStyleUnit_Percent ||
143 0 : IsCalcUnit();
144 : }
145 :
146 : // Does this calc() expression have any percentages inside it? Can be
147 : // called only when IsCalcUnit() is true.
148 0 : bool CalcHasPercent() const {
149 0 : return GetCalcValue()->mHasPercent;
150 : }
151 :
152 0 : bool HasPercent() const {
153 : return mUnit == eStyleUnit_Percent ||
154 0 : (IsCalcUnit() && CalcHasPercent());
155 : }
156 :
157 0 : bool ConvertsToLength() const {
158 : return mUnit == eStyleUnit_Coord ||
159 0 : (IsCalcUnit() && !CalcHasPercent());
160 : }
161 :
162 : nscoord GetCoordValue() const;
163 : PRInt32 GetIntValue() const;
164 : float GetPercentValue() const;
165 : float GetFactorValue() const;
166 : float GetAngleValue() const;
167 : double GetAngleValueInRadians() const;
168 : Calc* GetCalcValue() const;
169 : void GetUnionValue(nsStyleUnion& aValue) const;
170 :
171 : void Reset(); // sets to null
172 : void SetCoordValue(nscoord aValue);
173 : void SetIntValue(PRInt32 aValue, nsStyleUnit aUnit);
174 : void SetPercentValue(float aValue);
175 : void SetFactorValue(float aValue);
176 : void SetAngleValue(float aValue, nsStyleUnit aUnit);
177 : void SetNormalValue();
178 : void SetAutoValue();
179 : void SetNoneValue();
180 : void SetCalcValue(Calc* aValue);
181 :
182 : private:
183 : nsStyleUnit mUnit;
184 : nsStyleUnion mValue;
185 : };
186 :
187 : /**
188 : * Class that represents a set of top/right/bottom/left nsStyleCoords.
189 : * This is commonly used to hold the widths of the borders, margins,
190 : * or paddings of a box.
191 : */
192 : class nsStyleSides {
193 : public:
194 : nsStyleSides();
195 :
196 : // nsStyleSides& operator=(const nsStyleSides& aCopy); // use compiler's version
197 : bool operator==(const nsStyleSides& aOther) const;
198 : bool operator!=(const nsStyleSides& aOther) const;
199 :
200 : inline nsStyleUnit GetUnit(mozilla::css::Side aSide) const;
201 : inline nsStyleUnit GetLeftUnit() const;
202 : inline nsStyleUnit GetTopUnit() const;
203 : inline nsStyleUnit GetRightUnit() const;
204 : inline nsStyleUnit GetBottomUnit() const;
205 :
206 : inline nsStyleCoord Get(mozilla::css::Side aSide) const;
207 : inline nsStyleCoord GetLeft() const;
208 : inline nsStyleCoord GetTop() const;
209 : inline nsStyleCoord GetRight() const;
210 : inline nsStyleCoord GetBottom() const;
211 :
212 : void Reset();
213 :
214 : inline void Set(mozilla::css::Side aSide, const nsStyleCoord& aCoord);
215 : inline void SetLeft(const nsStyleCoord& aCoord);
216 : inline void SetTop(const nsStyleCoord& aCoord);
217 : inline void SetRight(const nsStyleCoord& aCoord);
218 : inline void SetBottom(const nsStyleCoord& aCoord);
219 :
220 : protected:
221 : PRUint8 mUnits[4];
222 : nsStyleUnion mValues[4];
223 : };
224 :
225 : /**
226 : * Class that represents a set of top-left/top-right/bottom-left/bottom-right
227 : * nsStyleCoord pairs. This is used to hold the dimensions of the
228 : * corners of a box (for, e.g., border-radius and outline-radius).
229 : */
230 : class nsStyleCorners {
231 : public:
232 : nsStyleCorners();
233 :
234 : // use compiler's version
235 : //nsStyleCorners& operator=(const nsStyleCorners& aCopy);
236 : bool operator==(const nsStyleCorners& aOther) const;
237 : bool operator!=(const nsStyleCorners& aOther) const;
238 :
239 : // aCorner is always one of NS_CORNER_* defined in nsStyleConsts.h
240 : inline nsStyleUnit GetUnit(PRUint8 aHalfCorner) const;
241 :
242 : inline nsStyleCoord Get(PRUint8 aHalfCorner) const;
243 :
244 : void Reset();
245 :
246 : inline void Set(PRUint8 aHalfCorner, const nsStyleCoord& aCoord);
247 :
248 : protected:
249 : PRUint8 mUnits[8];
250 : nsStyleUnion mValues[8];
251 : };
252 :
253 :
254 : // -------------------------
255 : // nsStyleCoord inlines
256 : //
257 0 : inline nsStyleCoord::nsStyleCoord(nscoord aValue, CoordConstructorType)
258 0 : : mUnit(eStyleUnit_Coord)
259 : {
260 0 : mValue.mInt = aValue;
261 0 : }
262 :
263 : // FIXME: In C++0x we can rely on the default copy constructor since
264 : // default copy construction is defined properly for unions. But when
265 : // can we actually use that? (It seems to work in gcc 4.4.)
266 0 : inline nsStyleCoord::nsStyleCoord(const nsStyleCoord& aCopy)
267 0 : : mUnit(aCopy.mUnit)
268 : {
269 0 : if ((eStyleUnit_Percent <= mUnit) && (mUnit < eStyleUnit_Coord)) {
270 0 : mValue.mFloat = aCopy.mValue.mFloat;
271 : }
272 0 : else if (IsPointerValue()) {
273 0 : mValue.mPointer = aCopy.mValue.mPointer;
274 : }
275 : else {
276 0 : mValue.mInt = aCopy.mValue.mInt;
277 : }
278 0 : }
279 :
280 0 : inline nsStyleCoord::nsStyleCoord(const nsStyleUnion& aValue, nsStyleUnit aUnit)
281 0 : : mUnit(aUnit), mValue(aValue)
282 : {
283 0 : }
284 :
285 0 : inline bool nsStyleCoord::operator!=(const nsStyleCoord& aOther) const
286 : {
287 0 : return !((*this) == aOther);
288 : }
289 :
290 0 : inline PRInt32 nsStyleCoord::GetCoordValue() const
291 : {
292 0 : NS_ASSERTION((mUnit == eStyleUnit_Coord), "not a coord value");
293 0 : if (mUnit == eStyleUnit_Coord) {
294 0 : return mValue.mInt;
295 : }
296 0 : return 0;
297 : }
298 :
299 0 : inline PRInt32 nsStyleCoord::GetIntValue() const
300 : {
301 0 : NS_ASSERTION((mUnit == eStyleUnit_Enumerated) ||
302 : (mUnit == eStyleUnit_Integer), "not an int value");
303 0 : if ((mUnit == eStyleUnit_Enumerated) ||
304 : (mUnit == eStyleUnit_Integer)) {
305 0 : return mValue.mInt;
306 : }
307 0 : return 0;
308 : }
309 :
310 0 : inline float nsStyleCoord::GetPercentValue() const
311 : {
312 0 : NS_ASSERTION(mUnit == eStyleUnit_Percent, "not a percent value");
313 0 : if (mUnit == eStyleUnit_Percent) {
314 0 : return mValue.mFloat;
315 : }
316 0 : return 0.0f;
317 : }
318 :
319 0 : inline float nsStyleCoord::GetFactorValue() const
320 : {
321 0 : NS_ASSERTION(mUnit == eStyleUnit_Factor, "not a factor value");
322 0 : if (mUnit == eStyleUnit_Factor) {
323 0 : return mValue.mFloat;
324 : }
325 0 : return 0.0f;
326 : }
327 :
328 0 : inline float nsStyleCoord::GetAngleValue() const
329 : {
330 0 : NS_ASSERTION(mUnit >= eStyleUnit_Degree &&
331 : mUnit <= eStyleUnit_Turn, "not an angle value");
332 0 : if (mUnit >= eStyleUnit_Degree && mUnit <= eStyleUnit_Turn) {
333 0 : return mValue.mFloat;
334 : }
335 0 : return 0.0f;
336 : }
337 :
338 0 : inline nsStyleCoord::Calc* nsStyleCoord::GetCalcValue() const
339 : {
340 0 : NS_ASSERTION(IsCalcUnit(), "not a pointer value");
341 0 : if (IsCalcUnit()) {
342 0 : return static_cast<Calc*>(mValue.mPointer);
343 : }
344 0 : return nsnull;
345 : }
346 :
347 :
348 0 : inline void nsStyleCoord::GetUnionValue(nsStyleUnion& aValue) const
349 : {
350 0 : aValue = mValue;
351 0 : }
352 :
353 : // -------------------------
354 : // nsStyleSides inlines
355 : //
356 0 : inline bool nsStyleSides::operator!=(const nsStyleSides& aOther) const
357 : {
358 0 : return !((*this) == aOther);
359 : }
360 :
361 0 : inline nsStyleUnit nsStyleSides::GetUnit(mozilla::css::Side aSide) const
362 : {
363 0 : return (nsStyleUnit)mUnits[aSide];
364 : }
365 :
366 0 : inline nsStyleUnit nsStyleSides::GetLeftUnit() const
367 : {
368 0 : return GetUnit(NS_SIDE_LEFT);
369 : }
370 :
371 0 : inline nsStyleUnit nsStyleSides::GetTopUnit() const
372 : {
373 0 : return GetUnit(NS_SIDE_TOP);
374 : }
375 :
376 0 : inline nsStyleUnit nsStyleSides::GetRightUnit() const
377 : {
378 0 : return GetUnit(NS_SIDE_RIGHT);
379 : }
380 :
381 0 : inline nsStyleUnit nsStyleSides::GetBottomUnit() const
382 : {
383 0 : return GetUnit(NS_SIDE_BOTTOM);
384 : }
385 :
386 0 : inline nsStyleCoord nsStyleSides::Get(mozilla::css::Side aSide) const
387 : {
388 0 : return nsStyleCoord(mValues[aSide], nsStyleUnit(mUnits[aSide]));
389 : }
390 :
391 0 : inline nsStyleCoord nsStyleSides::GetLeft() const
392 : {
393 0 : return Get(NS_SIDE_LEFT);
394 : }
395 :
396 0 : inline nsStyleCoord nsStyleSides::GetTop() const
397 : {
398 0 : return Get(NS_SIDE_TOP);
399 : }
400 :
401 0 : inline nsStyleCoord nsStyleSides::GetRight() const
402 : {
403 0 : return Get(NS_SIDE_RIGHT);
404 : }
405 :
406 0 : inline nsStyleCoord nsStyleSides::GetBottom() const
407 : {
408 0 : return Get(NS_SIDE_BOTTOM);
409 : }
410 :
411 0 : inline void nsStyleSides::Set(mozilla::css::Side aSide, const nsStyleCoord& aCoord)
412 : {
413 0 : mUnits[aSide] = aCoord.GetUnit();
414 0 : aCoord.GetUnionValue(mValues[aSide]);
415 0 : }
416 :
417 0 : inline void nsStyleSides::SetLeft(const nsStyleCoord& aCoord)
418 : {
419 0 : Set(NS_SIDE_LEFT, aCoord);
420 0 : }
421 :
422 0 : inline void nsStyleSides::SetTop(const nsStyleCoord& aCoord)
423 : {
424 0 : Set(NS_SIDE_TOP, aCoord);
425 0 : }
426 :
427 0 : inline void nsStyleSides::SetRight(const nsStyleCoord& aCoord)
428 : {
429 0 : Set(NS_SIDE_RIGHT, aCoord);
430 0 : }
431 :
432 0 : inline void nsStyleSides::SetBottom(const nsStyleCoord& aCoord)
433 : {
434 0 : Set(NS_SIDE_BOTTOM, aCoord);
435 0 : }
436 :
437 : // -------------------------
438 : // nsStyleCorners inlines
439 : //
440 0 : inline bool nsStyleCorners::operator!=(const nsStyleCorners& aOther) const
441 : {
442 0 : return !((*this) == aOther);
443 : }
444 :
445 : inline nsStyleUnit nsStyleCorners::GetUnit(PRUint8 aCorner) const
446 : {
447 : return (nsStyleUnit)mUnits[aCorner];
448 : }
449 :
450 0 : inline nsStyleCoord nsStyleCorners::Get(PRUint8 aCorner) const
451 : {
452 0 : return nsStyleCoord(mValues[aCorner], nsStyleUnit(mUnits[aCorner]));
453 : }
454 :
455 0 : inline void nsStyleCorners::Set(PRUint8 aCorner, const nsStyleCoord& aCoord)
456 : {
457 0 : mUnits[aCorner] = aCoord.GetUnit();
458 0 : aCoord.GetUnionValue(mValues[aCorner]);
459 0 : }
460 :
461 : #endif /* nsStyleCoord_h___ */
|