Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / layout / style / nsCSSValue.h
blob367ca12fc0f19d054b192e3663a06088b5a1c498
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
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/
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.
15 * The Original Code is mozilla.org code.
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.
22 * Contributor(s):
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.
36 * ***** END LICENSE BLOCK ***** */
38 /* representation of simple property values within CSS declarations */
40 #ifndef nsCSSValue_h___
41 #define nsCSSValue_h___
43 #include "nsCOMPtr.h"
44 #include "nsCRTGlue.h"
45 #include "nsCSSKeywords.h"
46 #include "nsCSSProperty.h"
47 #include "nsColor.h"
48 #include "nsCoord.h"
49 #include "nsString.h"
50 #include "nsStringBuffer.h"
51 #include "nsTArray.h"
52 #include "mozilla/mozalloc.h"
54 class imgIRequest;
55 class nsIDocument;
56 class nsIPrincipal;
57 class nsPresContext;
58 class nsIURI;
60 // Deletes a linked list iteratively to avoid blowing up the stack (bug 456196).
61 #define NS_CSS_DELETE_LIST_MEMBER(type_, ptr_, member_) \
62 { \
63 type_ *cur = (ptr_)->member_; \
64 (ptr_)->member_ = nsnull; \
65 while (cur) { \
66 type_ *next = cur->member_; \
67 cur->member_ = nsnull; \
68 delete cur; \
69 cur = next; \
70 } \
73 // Clones a linked list iteratively to avoid blowing up the stack.
74 // If it fails to clone the entire list then 'to_' is deleted and
75 // we return null.
76 #define NS_CSS_CLONE_LIST_MEMBER(type_, from_, member_, to_, args_) \
77 { \
78 type_ *dest = (to_); \
79 (to_)->member_ = nsnull; \
80 for (const type_ *src = (from_)->member_; src; src = src->member_) { \
81 type_ *clone = src->Clone args_; \
82 if (!clone) { \
83 delete (to_); \
84 return nsnull; \
85 } \
86 dest->member_ = clone; \
87 dest = clone; \
88 } \
91 enum nsCSSUnit {
92 eCSSUnit_Null = 0, // (n/a) null unit, value is not specified
93 eCSSUnit_Auto = 1, // (n/a) value is algorithmic
94 eCSSUnit_Inherit = 2, // (n/a) value is inherited
95 eCSSUnit_Initial = 3, // (n/a) value is default UA value
96 eCSSUnit_None = 4, // (n/a) value is none
97 eCSSUnit_Normal = 5, // (n/a) value is normal (algorithmic, different than auto)
98 eCSSUnit_System_Font = 6, // (n/a) value is -moz-use-system-font
99 eCSSUnit_All = 7, // (n/a) value is all
100 eCSSUnit_Dummy = 8, // (n/a) a fake but specified value, used
101 // only in temporary values
102 eCSSUnit_DummyInherit = 9, // (n/a) a fake but specified value, used
103 // only in temporary values
105 eCSSUnit_String = 11, // (PRUnichar*) a string value
106 eCSSUnit_Ident = 12, // (PRUnichar*) a string value
107 eCSSUnit_Families = 13, // (PRUnichar*) a string value
108 eCSSUnit_Attr = 14, // (PRUnichar*) a attr(string) value
109 eCSSUnit_Local_Font = 15, // (PRUnichar*) a local font name
110 eCSSUnit_Font_Format = 16, // (PRUnichar*) a font format name
111 eCSSUnit_Element = 17, // (PRUnichar*) an element id
113 eCSSUnit_Array = 20, // (nsCSSValue::Array*) a list of values
114 eCSSUnit_Counter = 21, // (nsCSSValue::Array*) a counter(string,[string]) value
115 eCSSUnit_Counters = 22, // (nsCSSValue::Array*) a counters(string,string[,string]) value
116 eCSSUnit_Cubic_Bezier = 23, // (nsCSSValue::Array*) a list of float values
117 eCSSUnit_Function = 24, // (nsCSSValue::Array*) a function with
118 // parameters. First elem of array is name,
119 // the rest of the values are arguments.
121 // The top level of a calc() expression is eCSSUnit_Calc. All
122 // remaining eCSSUnit_Calc_* units only occur inside these toplevel
123 // calc values.
125 // eCSSUnit_Calc has an array with exactly 1 element. eCSSUnit_Calc
126 // exists so we can distinguish calc(2em) from 2em as specified values
127 // (but we drop this distinction for nsStyleCoord when we store
128 // computed values).
129 eCSSUnit_Calc = 25, // (nsCSSValue::Array*) calc() value
130 // Plus, Minus, Times_* and Divided have arrays with exactly 2
131 // elements. a + b + c + d is grouped as ((a + b) + c) + d
132 eCSSUnit_Calc_Plus = 26, // (nsCSSValue::Array*) + node within calc()
133 eCSSUnit_Calc_Minus = 27, // (nsCSSValue::Array*) - within calc
134 eCSSUnit_Calc_Times_L = 28, // (nsCSSValue::Array*) num * val within calc
135 eCSSUnit_Calc_Times_R = 29, // (nsCSSValue::Array*) val * num within calc
136 eCSSUnit_Calc_Divided = 30, // (nsCSSValue::Array*) / within calc
138 eCSSUnit_URL = 40, // (nsCSSValue::URL*) value
139 eCSSUnit_Image = 41, // (nsCSSValue::Image*) value
140 eCSSUnit_Gradient = 42, // (nsCSSValueGradient*) value
142 eCSSUnit_Pair = 50, // (nsCSSValuePair*) pair of values
143 eCSSUnit_Rect = 51, // (nsCSSRect*) rectangle (four values)
144 eCSSUnit_List = 52, // (nsCSSValueList*) list of values
145 eCSSUnit_ListDep = 53, // (nsCSSValueList*) same as List
146 // but does not own the list
147 eCSSUnit_PairList = 54, // (nsCSSValuePairList*) list of value pairs
148 eCSSUnit_PairListDep = 55, // (nsCSSValuePairList*) same as PairList
149 // but does not own the list
151 eCSSUnit_Integer = 70, // (int) simple value
152 eCSSUnit_Enumerated = 71, // (int) value has enumerated meaning
154 eCSSUnit_EnumColor = 80, // (int) enumerated color (kColorKTable)
155 eCSSUnit_Color = 81, // (nscolor) an RGBA value
157 eCSSUnit_Percent = 90, // (float) 1.0 == 100%) value is percentage of something
158 eCSSUnit_Number = 91, // (float) value is numeric (usually multiplier, different behavior that percent)
160 // Physical length units
161 eCSSUnit_PhysicalMillimeter = 200, // (float) 1/25.4 inch
163 // Length units - relative
164 // Font relative measure
165 eCSSUnit_EM = 800, // (float) == current font size
166 eCSSUnit_XHeight = 801, // (float) distance from top of lower case x to baseline
167 eCSSUnit_Char = 802, // (float) number of characters, used for width with monospace font
168 eCSSUnit_RootEM = 803, // (float) == root element font size
170 // Screen relative measure
171 eCSSUnit_Point = 900, // (float) 4/3 of a CSS pixel
172 eCSSUnit_Inch = 901, // (float) 96 CSS pixels
173 eCSSUnit_Millimeter = 902, // (float) 96/25.4 CSS pixels
174 eCSSUnit_Centimeter = 903, // (float) 96/2.54 CSS pixels
175 eCSSUnit_Pica = 904, // (float) 12 points == 16 CSS pixls
176 eCSSUnit_Pixel = 905, // (float) CSS pixel unit
178 // Angular units
179 eCSSUnit_Degree = 1000, // (float) 360 per circle
180 eCSSUnit_Grad = 1001, // (float) 400 per circle
181 eCSSUnit_Radian = 1002, // (float) 2*pi per circle
183 // Frequency units
184 eCSSUnit_Hertz = 2000, // (float) 1/seconds
185 eCSSUnit_Kilohertz = 2001, // (float) 1000 Hertz
187 // Time units
188 eCSSUnit_Seconds = 3000, // (float) Standard time
189 eCSSUnit_Milliseconds = 3001 // (float) 1/1000 second
192 struct nsCSSValueGradient;
193 struct nsCSSValuePair;
194 struct nsCSSValuePair_heap;
195 struct nsCSSRect;
196 struct nsCSSRect_heap;
197 struct nsCSSValueList;
198 struct nsCSSValueList_heap;
199 struct nsCSSValuePairList;
200 struct nsCSSValuePairList_heap;
202 class nsCSSValue {
203 public:
204 struct Array;
205 friend struct Array;
207 struct URL;
208 friend struct URL;
210 struct Image;
211 friend struct Image;
213 // for valueless units only (null, auto, inherit, none, all, normal)
214 explicit nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null)
215 : mUnit(aUnit)
217 NS_ABORT_IF_FALSE(aUnit <= eCSSUnit_DummyInherit, "not a valueless unit");
220 nsCSSValue(PRInt32 aValue, nsCSSUnit aUnit);
221 nsCSSValue(float aValue, nsCSSUnit aUnit);
222 nsCSSValue(const nsString& aValue, nsCSSUnit aUnit);
223 nsCSSValue(Array* aArray, nsCSSUnit aUnit);
224 explicit nsCSSValue(URL* aValue);
225 explicit nsCSSValue(Image* aValue);
226 explicit nsCSSValue(nsCSSValueGradient* aValue);
227 nsCSSValue(const nsCSSValue& aCopy);
228 ~nsCSSValue() { Reset(); }
230 nsCSSValue& operator=(const nsCSSValue& aCopy);
231 PRBool operator==(const nsCSSValue& aOther) const;
233 PRBool operator!=(const nsCSSValue& aOther) const
235 return !(*this == aOther);
239 * Serialize |this| as a specified value for |aProperty| and append
240 * it to |aResult|.
242 void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
244 nsCSSUnit GetUnit() const { return mUnit; }
245 PRBool IsLengthUnit() const
246 { return eCSSUnit_PhysicalMillimeter <= mUnit && mUnit <= eCSSUnit_Pixel; }
248 * A "fixed" length unit is one that means a specific physical length
249 * which we try to match based on the physical characteristics of an
250 * output device.
252 PRBool IsFixedLengthUnit() const
253 { return mUnit == eCSSUnit_PhysicalMillimeter; }
255 * What the spec calls relative length units is, for us, split
256 * between relative length units and pixel length units.
258 * A "relative" length unit is a multiple of some derived metric,
259 * such as a font em-size, which itself was controlled by an input CSS
260 * length. Relative length units should not be scaled by zooming, since
261 * the underlying CSS length would already have been scaled.
263 PRBool IsRelativeLengthUnit() const
264 { return eCSSUnit_EM <= mUnit && mUnit <= eCSSUnit_RootEM; }
266 * A "pixel" length unit is a some multiple of CSS pixels.
268 PRBool IsPixelLengthUnit() const
269 { return eCSSUnit_Point <= mUnit && mUnit <= eCSSUnit_Pixel; }
270 PRBool IsAngularUnit() const
271 { return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Radian; }
272 PRBool IsFrequencyUnit() const
273 { return eCSSUnit_Hertz <= mUnit && mUnit <= eCSSUnit_Kilohertz; }
274 PRBool IsTimeUnit() const
275 { return eCSSUnit_Seconds <= mUnit && mUnit <= eCSSUnit_Milliseconds; }
276 PRBool IsCalcUnit() const
277 { return eCSSUnit_Calc <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
279 PRBool UnitHasStringValue() const
280 { return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Element; }
281 PRBool UnitHasArrayValue() const
282 { return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
284 PRInt32 GetIntValue() const
286 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Integer ||
287 mUnit == eCSSUnit_Enumerated ||
288 mUnit == eCSSUnit_EnumColor,
289 "not an int value");
290 return mValue.mInt;
293 float GetPercentValue() const
295 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Percent, "not a percent value");
296 return mValue.mFloat;
299 float GetFloatValue() const
301 NS_ABORT_IF_FALSE(eCSSUnit_Number <= mUnit, "not a float value");
302 return mValue.mFloat;
305 float GetAngleValue() const
307 NS_ABORT_IF_FALSE(eCSSUnit_Degree <= mUnit &&
308 mUnit <= eCSSUnit_Radian, "not an angle value");
309 return mValue.mFloat;
312 // Converts any angle to radians.
313 double GetAngleValueInRadians() const;
315 nsAString& GetStringValue(nsAString& aBuffer) const
317 NS_ABORT_IF_FALSE(UnitHasStringValue(), "not a string value");
318 aBuffer.Truncate();
319 PRUint32 len = NS_strlen(GetBufferValue(mValue.mString));
320 mValue.mString->ToString(len, aBuffer);
321 return aBuffer;
324 const PRUnichar* GetStringBufferValue() const
326 NS_ABORT_IF_FALSE(UnitHasStringValue(), "not a string value");
327 return GetBufferValue(mValue.mString);
330 nscolor GetColorValue() const
332 NS_ABORT_IF_FALSE((mUnit == eCSSUnit_Color), "not a color value");
333 return mValue.mColor;
336 PRBool IsNonTransparentColor() const;
338 Array* GetArrayValue() const
340 NS_ABORT_IF_FALSE(UnitHasArrayValue(), "not an array value");
341 return mValue.mArray;
344 nsIURI* GetURLValue() const
346 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
347 "not a URL value");
348 return mUnit == eCSSUnit_URL ?
349 mValue.mURL->mURI : mValue.mImage->mURI;
352 nsCSSValueGradient* GetGradientValue() const
354 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Gradient, "not a gradient value");
355 return mValue.mGradient;
358 // bodies of these are below
359 inline nsCSSValuePair& GetPairValue();
360 inline const nsCSSValuePair& GetPairValue() const;
362 inline nsCSSRect& GetRectValue();
363 inline const nsCSSRect& GetRectValue() const;
365 inline nsCSSValueList* GetListValue();
366 inline const nsCSSValueList* GetListValue() const;
368 inline nsCSSValuePairList* GetPairListValue();
369 inline const nsCSSValuePairList* GetPairListValue() const;
371 URL* GetURLStructValue() const
373 // Not allowing this for Image values, because if the caller takes
374 // a ref to them they won't be able to delete them properly.
375 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_URL, "not a URL value");
376 return mValue.mURL;
379 const PRUnichar* GetOriginalURLValue() const
381 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
382 "not a URL value");
383 return GetBufferValue(mUnit == eCSSUnit_URL ?
384 mValue.mURL->mString :
385 mValue.mImage->mString);
388 // Not making this inline because that would force us to include
389 // imgIRequest.h, which leads to REQUIRES hell, since this header is included
390 // all over.
391 imgIRequest* GetImageValue() const;
393 nscoord GetFixedLength(nsPresContext* aPresContext) const;
394 nscoord GetPixelLength() const;
396 void Reset() // sets to null
398 if (mUnit != eCSSUnit_Null)
399 DoReset();
401 private:
402 void DoReset();
404 public:
405 void SetIntValue(PRInt32 aValue, nsCSSUnit aUnit);
406 void SetPercentValue(float aValue);
407 void SetFloatValue(float aValue, nsCSSUnit aUnit);
408 void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
409 void SetColorValue(nscolor aValue);
410 void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
411 void SetURLValue(nsCSSValue::URL* aURI);
412 void SetImageValue(nsCSSValue::Image* aImage);
413 void SetGradientValue(nsCSSValueGradient* aGradient);
414 void SetPairValue(const nsCSSValuePair* aPair);
415 void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
416 void SetDependentListValue(nsCSSValueList* aList);
417 void SetDependentPairListValue(nsCSSValuePairList* aList);
418 void SetAutoValue();
419 void SetInheritValue();
420 void SetInitialValue();
421 void SetNoneValue();
422 void SetAllValue();
423 void SetNormalValue();
424 void SetSystemFontValue();
425 void SetDummyValue();
426 void SetDummyInheritValue();
428 // These are a little different - they allocate storage for you and
429 // return a handle.
430 nsCSSRect& SetRectValue();
431 nsCSSValueList* SetListValue();
432 nsCSSValuePairList* SetPairListValue();
434 void StartImageLoad(nsIDocument* aDocument) const; // Only pretend const
436 // Initializes as a function value with the specified function id.
437 Array* InitFunction(nsCSSKeyword aFunctionId, PRUint32 aNumArgs);
438 // Checks if this is a function value with the specified function id.
439 PRBool EqualsFunction(nsCSSKeyword aFunctionId) const;
441 // Returns an already addrefed buffer. Can return null on allocation
442 // failure.
443 static already_AddRefed<nsStringBuffer>
444 BufferFromString(const nsString& aValue);
446 struct URL {
447 // Methods are not inline because using an nsIPrincipal means requiring
448 // caps, which leads to REQUIRES hell, since this header is included all
449 // over.
451 // aString must not be null.
452 // aOriginPrincipal must not be null.
453 URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
454 nsIPrincipal* aOriginPrincipal);
456 ~URL();
458 PRBool operator==(const URL& aOther) const;
460 // URIEquals only compares URIs and principals (unlike operator==, which
461 // also compares the original strings). URIEquals also assumes that the
462 // mURI member of both URL objects is non-null. Do NOT call this method
463 // unless you're sure this is the case.
464 PRBool URIEquals(const URL& aOther) const;
466 nsCOMPtr<nsIURI> mURI; // null == invalid URL
467 nsStringBuffer* mString; // Could use nsRefPtr, but it'd add useless
468 // null-checks; this is never null.
469 nsCOMPtr<nsIURI> mReferrer;
470 nsCOMPtr<nsIPrincipal> mOriginPrincipal;
472 NS_INLINE_DECL_REFCOUNTING(nsCSSValue::URL)
474 protected:
476 // not to be implemented
477 URL(const URL& aOther);
478 URL& operator=(const URL& aOther);
481 struct Image : public URL {
482 // Not making the constructor and destructor inline because that would
483 // force us to include imgIRequest.h, which leads to REQUIRES hell, since
484 // this header is included all over.
485 // aString must not be null.
486 Image(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
487 nsIPrincipal* aOriginPrincipal, nsIDocument* aDocument);
488 ~Image();
490 // Inherit operator== from nsCSSValue::URL
492 nsCOMPtr<imgIRequest> mRequest; // null == image load blocked or somehow failed
494 // Override AddRef and Release to not only log ourselves correctly, but
495 // also so that we delete correctly without a virtual destructor
496 NS_INLINE_DECL_REFCOUNTING(nsCSSValue::Image)
499 private:
500 static const PRUnichar* GetBufferValue(nsStringBuffer* aBuffer) {
501 return static_cast<PRUnichar*>(aBuffer->Data());
504 protected:
505 nsCSSUnit mUnit;
506 union {
507 PRInt32 mInt;
508 float mFloat;
509 // Note: the capacity of the buffer may exceed the length of the string.
510 // If we're of a string type, mString is not null.
511 nsStringBuffer* mString;
512 nscolor mColor;
513 Array* mArray;
514 URL* mURL;
515 Image* mImage;
516 nsCSSValueGradient* mGradient;
517 nsCSSValuePair_heap* mPair;
518 nsCSSRect_heap* mRect;
519 nsCSSValueList_heap* mList;
520 nsCSSValueList* mListDependent;
521 nsCSSValuePairList_heap* mPairList;
522 nsCSSValuePairList* mPairListDependent;
523 } mValue;
526 struct nsCSSValue::Array {
528 // return |Array| with reference count of zero
529 static Array* Create(size_t aItemCount) {
530 return new (aItemCount) Array(aItemCount);
533 static Array* Create(const mozilla::fallible_t& aFallible,
534 size_t aItemCount) {
535 return new (aFallible, aItemCount) Array(aItemCount);
538 nsCSSValue& operator[](size_t aIndex) {
539 NS_ABORT_IF_FALSE(aIndex < mCount, "out of range");
540 return mArray[aIndex];
543 const nsCSSValue& operator[](size_t aIndex) const {
544 NS_ABORT_IF_FALSE(aIndex < mCount, "out of range");
545 return mArray[aIndex];
548 nsCSSValue& Item(size_t aIndex) { return (*this)[aIndex]; }
549 const nsCSSValue& Item(size_t aIndex) const { return (*this)[aIndex]; }
551 size_t Count() const { return mCount; }
553 PRBool operator==(const Array& aOther) const
555 if (mCount != aOther.mCount)
556 return PR_FALSE;
557 for (size_t i = 0; i < mCount; ++i)
558 if ((*this)[i] != aOther[i])
559 return PR_FALSE;
560 return PR_TRUE;
563 // XXXdholbert This uses a size_t ref count. Should we use a variant
564 // of NS_INLINE_DECL_REFCOUNTING that takes a type as an argument?
565 void AddRef() {
566 if (mRefCnt == size_t(-1)) { // really want SIZE_MAX
567 NS_WARNING("refcount overflow, leaking nsCSSValue::Array");
568 return;
570 ++mRefCnt;
571 NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Array", sizeof(*this));
573 void Release() {
574 if (mRefCnt == size_t(-1)) { // really want SIZE_MAX
575 NS_WARNING("refcount overflow, leaking nsCSSValue::Array");
576 return;
578 --mRefCnt;
579 NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Array");
580 if (mRefCnt == 0)
581 delete this;
584 private:
586 size_t mRefCnt;
587 const size_t mCount;
588 // This must be the last sub-object, since we extend this array to
589 // be of size mCount; it needs to be a sub-object so it gets proper
590 // alignment.
591 nsCSSValue mArray[1];
593 void* operator new(size_t aSelfSize, size_t aItemCount) CPP_THROW_NEW {
594 NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have a 0 item count");
595 return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1));
598 void* operator new(size_t aSelfSize, const mozilla::fallible_t& aFallible,
599 size_t aItemCount) CPP_THROW_NEW {
600 NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have a 0 item count");
601 return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1),
602 aFallible);
605 void operator delete(void* aPtr) { ::operator delete(aPtr); }
607 nsCSSValue* First() { return mArray; }
609 const nsCSSValue* First() const { return mArray; }
611 #define CSSVALUE_LIST_FOR_EXTRA_VALUES(var) \
612 for (nsCSSValue *var = First() + 1, *var##_end = First() + mCount; \
613 var != var##_end; ++var)
615 Array(size_t aItemCount)
616 : mRefCnt(0)
617 , mCount(aItemCount)
619 MOZ_COUNT_CTOR(nsCSSValue::Array);
620 CSSVALUE_LIST_FOR_EXTRA_VALUES(val) {
621 new (val) nsCSSValue();
625 ~Array()
627 MOZ_COUNT_DTOR(nsCSSValue::Array);
628 CSSVALUE_LIST_FOR_EXTRA_VALUES(val) {
629 val->~nsCSSValue();
633 #undef CSSVALUE_LIST_FOR_EXTRA_VALUES
635 private:
636 // not to be implemented
637 Array(const Array& aOther);
638 Array& operator=(const Array& aOther);
641 // Prefer nsCSSValue::Array for lists of fixed size.
642 struct nsCSSValueList {
643 nsCSSValueList() : mNext(nsnull) { MOZ_COUNT_CTOR(nsCSSValueList); }
644 ~nsCSSValueList();
646 nsCSSValueList* Clone() const; // makes a deep copy
647 void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
649 bool operator==(nsCSSValueList const& aOther) const;
650 bool operator!=(const nsCSSValueList& aOther) const
651 { return !(*this == aOther); }
653 nsCSSValue mValue;
654 nsCSSValueList* mNext;
656 private:
657 nsCSSValueList(const nsCSSValueList& aCopy) // makes a shallow copy
658 : mValue(aCopy.mValue), mNext(nsnull)
660 MOZ_COUNT_CTOR(nsCSSValueList);
664 // nsCSSValueList_heap differs from nsCSSValueList only in being
665 // refcounted. It should not be necessary to use this class directly;
666 // it's an implementation detail of nsCSSValue.
667 struct nsCSSValueList_heap : public nsCSSValueList {
668 NS_INLINE_DECL_REFCOUNTING(nsCSSValueList_heap)
671 // This has to be here so that the relationship between nsCSSValueList
672 // and nsCSSValueList_heap is visible.
673 inline nsCSSValueList*
674 nsCSSValue::GetListValue()
676 if (mUnit == eCSSUnit_List)
677 return mValue.mList;
678 else {
679 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_ListDep, "not a pairlist value");
680 return mValue.mListDependent;
684 inline const nsCSSValueList*
685 nsCSSValue::GetListValue() const
687 if (mUnit == eCSSUnit_List)
688 return mValue.mList;
689 else {
690 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_ListDep, "not a pairlist value");
691 return mValue.mListDependent;
695 struct nsCSSRect {
696 nsCSSRect(void);
697 nsCSSRect(const nsCSSRect& aCopy);
698 ~nsCSSRect();
700 void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
702 PRBool operator==(const nsCSSRect& aOther) const {
703 return mTop == aOther.mTop &&
704 mRight == aOther.mRight &&
705 mBottom == aOther.mBottom &&
706 mLeft == aOther.mLeft;
709 PRBool operator!=(const nsCSSRect& aOther) const {
710 return mTop != aOther.mTop ||
711 mRight != aOther.mRight ||
712 mBottom != aOther.mBottom ||
713 mLeft != aOther.mLeft;
716 void SetAllSidesTo(const nsCSSValue& aValue);
718 void Reset() {
719 mTop.Reset();
720 mRight.Reset();
721 mBottom.Reset();
722 mLeft.Reset();
725 PRBool HasValue() const {
726 return
727 mTop.GetUnit() != eCSSUnit_Null ||
728 mRight.GetUnit() != eCSSUnit_Null ||
729 mBottom.GetUnit() != eCSSUnit_Null ||
730 mLeft.GetUnit() != eCSSUnit_Null;
733 nsCSSValue mTop;
734 nsCSSValue mRight;
735 nsCSSValue mBottom;
736 nsCSSValue mLeft;
738 typedef nsCSSValue nsCSSRect::*side_type;
739 static const side_type sides[4];
742 // nsCSSRect_heap differs from nsCSSRect only in being
743 // refcounted. It should not be necessary to use this class directly;
744 // it's an implementation detail of nsCSSValue.
745 struct nsCSSRect_heap : public nsCSSRect {
746 NS_INLINE_DECL_REFCOUNTING(nsCSSRect_heap)
749 // This has to be here so that the relationship between nsCSSRect
750 // and nsCSSRect_heap is visible.
751 inline nsCSSRect&
752 nsCSSValue::GetRectValue()
754 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Rect, "not a pair value");
755 return *mValue.mRect;
758 inline const nsCSSRect&
759 nsCSSValue::GetRectValue() const
761 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Rect, "not a pair value");
762 return *mValue.mRect;
765 struct nsCSSValuePair {
766 nsCSSValuePair()
768 MOZ_COUNT_CTOR(nsCSSValuePair);
770 nsCSSValuePair(nsCSSUnit aUnit)
771 : mXValue(aUnit), mYValue(aUnit)
773 MOZ_COUNT_CTOR(nsCSSValuePair);
775 nsCSSValuePair(const nsCSSValue& aXValue, const nsCSSValue& aYValue)
776 : mXValue(aXValue), mYValue(aYValue)
778 MOZ_COUNT_CTOR(nsCSSValuePair);
780 nsCSSValuePair(const nsCSSValuePair& aCopy)
781 : mXValue(aCopy.mXValue), mYValue(aCopy.mYValue)
783 MOZ_COUNT_CTOR(nsCSSValuePair);
785 ~nsCSSValuePair()
787 MOZ_COUNT_DTOR(nsCSSValuePair);
790 PRBool operator==(const nsCSSValuePair& aOther) const {
791 return mXValue == aOther.mXValue &&
792 mYValue == aOther.mYValue;
795 PRBool operator!=(const nsCSSValuePair& aOther) const {
796 return mXValue != aOther.mXValue ||
797 mYValue != aOther.mYValue;
800 void SetBothValuesTo(const nsCSSValue& aValue) {
801 mXValue = aValue;
802 mYValue = aValue;
805 void Reset() {
806 mXValue.Reset();
807 mYValue.Reset();
810 PRBool HasValue() const {
811 return mXValue.GetUnit() != eCSSUnit_Null ||
812 mYValue.GetUnit() != eCSSUnit_Null;
815 void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
817 nsCSSValue mXValue;
818 nsCSSValue mYValue;
821 // nsCSSValuePair_heap differs from nsCSSValuePair only in being
822 // refcounted. It should not be necessary to use this class directly;
823 // it's an implementation detail of nsCSSValue.
824 struct nsCSSValuePair_heap : public nsCSSValuePair {
825 // forward constructor
826 nsCSSValuePair_heap(const nsCSSValue& aXValue, const nsCSSValue& aYValue)
827 : nsCSSValuePair(aXValue, aYValue)
830 NS_INLINE_DECL_REFCOUNTING(nsCSSValuePair_heap)
833 // This has to be here so that the relationship between nsCSSValuePair
834 // and nsCSSValuePair_heap is visible.
835 inline nsCSSValuePair&
836 nsCSSValue::GetPairValue()
838 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Pair, "not a pair value");
839 return *mValue.mPair;
842 inline const nsCSSValuePair&
843 nsCSSValue::GetPairValue() const
845 NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Pair, "not a pair value");
846 return *mValue.mPair;
849 // Maybe should be replaced with nsCSSValueList and nsCSSValue::Array?
850 struct nsCSSValuePairList {
851 nsCSSValuePairList() : mNext(nsnull) { MOZ_COUNT_CTOR(nsCSSValuePairList); }
852 ~nsCSSValuePairList();
854 nsCSSValuePairList* Clone() const; // makes a deep copy
855 void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
857 bool operator==(const nsCSSValuePairList& aOther) const;
858 bool operator!=(const nsCSSValuePairList& aOther) const
859 { return !(*this == aOther); }
861 nsCSSValue mXValue;
862 nsCSSValue mYValue;
863 nsCSSValuePairList* mNext;
865 private:
866 nsCSSValuePairList(const nsCSSValuePairList& aCopy) // makes a shallow copy
867 : mXValue(aCopy.mXValue), mYValue(aCopy.mYValue), mNext(nsnull)
869 MOZ_COUNT_CTOR(nsCSSValuePairList);
873 // nsCSSValuePairList_heap differs from nsCSSValuePairList only in being
874 // refcounted. It should not be necessary to use this class directly;
875 // it's an implementation detail of nsCSSValue.
876 struct nsCSSValuePairList_heap : public nsCSSValuePairList {
877 NS_INLINE_DECL_REFCOUNTING(nsCSSValuePairList_heap)
880 // This has to be here so that the relationship between nsCSSValuePairList
881 // and nsCSSValuePairList_heap is visible.
882 inline nsCSSValuePairList*
883 nsCSSValue::GetPairListValue()
885 if (mUnit == eCSSUnit_PairList)
886 return mValue.mPairList;
887 else {
888 NS_ABORT_IF_FALSE (mUnit == eCSSUnit_PairListDep, "not a pairlist value");
889 return mValue.mPairListDependent;
893 inline const nsCSSValuePairList*
894 nsCSSValue::GetPairListValue() const
896 if (mUnit == eCSSUnit_PairList)
897 return mValue.mPairList;
898 else {
899 NS_ABORT_IF_FALSE (mUnit == eCSSUnit_PairListDep, "not a pairlist value");
900 return mValue.mPairListDependent;
904 struct nsCSSValueGradientStop {
905 public:
906 nsCSSValueGradientStop();
907 // needed to keep bloat logs happy when we use the nsTArray in nsCSSValueGradient
908 nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther);
909 ~nsCSSValueGradientStop();
911 nsCSSValue mLocation;
912 nsCSSValue mColor;
914 PRBool operator==(const nsCSSValueGradientStop& aOther) const
916 return (mLocation == aOther.mLocation &&
917 mColor == aOther.mColor);
920 PRBool operator!=(const nsCSSValueGradientStop& aOther) const
922 return !(*this == aOther);
926 struct nsCSSValueGradient {
927 nsCSSValueGradient(PRBool aIsRadial, PRBool aIsRepeating);
929 // true if gradient is radial, false if it is linear
930 PRPackedBool mIsRadial;
931 PRPackedBool mIsRepeating;
932 // line position and angle
933 nsCSSValuePair mBgPos;
934 nsCSSValue mAngle;
936 // Only meaningful if mIsRadial is true
937 nsCSSValue mRadialShape;
938 nsCSSValue mRadialSize;
940 nsTArray<nsCSSValueGradientStop> mStops;
942 PRBool operator==(const nsCSSValueGradient& aOther) const
944 if (mIsRadial != aOther.mIsRadial ||
945 mIsRepeating != aOther.mIsRepeating ||
946 mBgPos != aOther.mBgPos ||
947 mAngle != aOther.mAngle ||
948 mRadialShape != aOther.mRadialShape ||
949 mRadialSize != aOther.mRadialSize)
950 return PR_FALSE;
952 if (mStops.Length() != aOther.mStops.Length())
953 return PR_FALSE;
955 for (PRUint32 i = 0; i < mStops.Length(); i++) {
956 if (mStops[i] != aOther.mStops[i])
957 return PR_FALSE;
960 return PR_TRUE;
963 PRBool operator!=(const nsCSSValueGradient& aOther) const
965 return !(*this == aOther);
968 NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient)
970 private:
971 // not to be implemented
972 nsCSSValueGradient(const nsCSSValueGradient& aOther);
973 nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther);
976 #endif /* nsCSSValue_h___ */