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 simple property values within CSS declarations */
8 
9 #ifndef nsCSSValue_h___
10 #define nsCSSValue_h___
11 
12 #include "mozilla/Attributes.h"
13 #include "mozilla/CORSMode.h"
14 #include "mozilla/MemoryReporting.h"
15 #include "mozilla/ServoTypes.h"
16 #include "mozilla/SheetType.h"
17 #include "mozilla/StyleComplexColor.h"
18 #include "mozilla/URLExtraData.h"
19 #include "mozilla/UniquePtr.h"
20 
21 #include "nsCSSKeywords.h"
22 #include "nsCSSPropertyID.h"
23 #include "nsCSSProps.h"
24 #include "nsColor.h"
25 #include "nsCoord.h"
26 #include "nsProxyRelease.h"
27 #include "nsRefPtrHashtable.h"
28 #include "nsString.h"
29 #include "nsStringBuffer.h"
30 #include "nsTArray.h"
31 #include "nsStyleConsts.h"
32 #include "nsStyleCoord.h"
33 #include "gfxFontFamilyList.h"
34 
35 #include <type_traits>
36 
37 class imgRequestProxy;
38 class nsAtom;
39 class nsIContent;
40 class nsIDocument;
41 class nsIPrincipal;
42 class nsIURI;
43 class nsPresContext;
44 template <class T>
45 class nsPtrHashKey;
46 struct RustString;
47 
48 namespace mozilla {
49 class CSSStyleSheet;
50 }  // namespace mozilla
51 
52 // Deletes a linked list iteratively to avoid blowing up the stack (bug 456196).
53 #define NS_CSS_DELETE_LIST_MEMBER(type_, ptr_, member_) \
54   {                                                     \
55     type_* cur = (ptr_)->member_;                       \
56     (ptr_)->member_ = nullptr;                          \
57     while (cur) {                                       \
58       type_* dlm_next = cur->member_;                   \
59       cur->member_ = nullptr;                           \
60       delete cur;                                       \
61       cur = dlm_next;                                   \
62     }                                                   \
63   }
64 // Ditto, but use NS_RELEASE instead of 'delete' (bug 1221902).
65 #define NS_CSS_NS_RELEASE_LIST_MEMBER(type_, ptr_, member_) \
66   {                                                         \
67     type_* cur = (ptr_)->member_;                           \
68     (ptr_)->member_ = nullptr;                              \
69     while (cur) {                                           \
70       type_* dlm_next = cur->member_;                       \
71       cur->member_ = nullptr;                               \
72       NS_RELEASE(cur);                                      \
73       cur = dlm_next;                                       \
74     }                                                       \
75   }
76 
77 // Clones a linked list iteratively to avoid blowing up the stack.
78 // If it fails to clone the entire list then 'to_' is deleted and
79 // we return null.
80 #define NS_CSS_CLONE_LIST_MEMBER(type_, from_, member_, to_, args_)      \
81   {                                                                      \
82     type_* dest = (to_);                                                 \
83     (to_)->member_ = nullptr;                                            \
84     for (const type_* src = (from_)->member_; src; src = src->member_) { \
85       type_* clm_clone = src->Clone args_;                               \
86       if (!clm_clone) {                                                  \
87         delete (to_);                                                    \
88         return nullptr;                                                  \
89       }                                                                  \
90       dest->member_ = clm_clone;                                         \
91       dest = clm_clone;                                                  \
92     }                                                                    \
93   }
94 
95 namespace mozilla {
96 namespace css {
97 
98 struct URLValueData {
99  protected:
100   // Methods are not inline because using an nsIPrincipal means requiring
101   // caps, which leads to REQUIRES hell, since this header is included all
102   // over.
103 
104   // For both constructors aString must not be null.
105   // For both constructors principal of aExtraData must not be null.
106   // Construct with a base URI; this will create the actual URI lazily from
107   // aString and aExtraData.
108   URLValueData(const nsAString& aString,
109                already_AddRefed<URLExtraData> aExtraData, CORSMode aCORSMode);
110   URLValueData(ServoRawOffsetArc<RustString> aString,
111                already_AddRefed<URLExtraData> aExtraData, CORSMode aCORSMode);
112   // Construct with the actual URI.
113   URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
114                const nsAString& aString,
115                already_AddRefed<URLExtraData> aExtraData, CORSMode aCORSMode);
116   URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
117                ServoRawOffsetArc<RustString> aString,
118                already_AddRefed<URLExtraData> aExtraData, CORSMode aCORSMode);
119 
120  public:
121   // Returns true iff all fields of the two URLValueData objects are equal.
122   //
123   // Only safe to call on the main thread, since this will call Equals on the
124   // nsIURI and nsIPrincipal objects stored on the URLValueData objects.
125   bool Equals(const URLValueData& aOther) const;
126 
127   // Returns true iff we know for sure, by comparing the mBaseURI pointer,
128   // the specified url() value mString, and the mIsLocalRef, that these
129   // two URLValueData objects represent the same computed url() value.
130   //
131   // Doesn't look at mReferrer or mOriginPrincipal.
132   //
133   // Safe to call from any thread.
134   bool DefinitelyEqualURIs(const URLValueData& aOther) const;
135 
136   // Smae as DefinitelyEqualURIs but additionally compares the nsIPrincipal
137   // pointers of the two URLValueData objects.
138   bool DefinitelyEqualURIsAndPrincipal(const URLValueData& aOther) const;
139 
140   nsIURI* GetURI() const;
141 
142   bool IsLocalRef() const;
143 
144   bool HasRef() const;
145 
146   // This function takes a guess whether the URL has a fragment, by searching
147   // for a hash character. It definitely returns false if we know it can't
148   // have a fragment because it has no hash character.
149   //
150   // MightHaveRef can be used in any thread, whereas HasRef can only be used
151   // in the main thread.
152   bool MightHaveRef() const;
153 
154   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLValueData)
155 
156   // When matching a url with mIsLocalRef set, resolve it against aURI;
157   // Otherwise, ignore aURL and return mURL directly.
158   already_AddRefed<nsIURI> ResolveLocalRef(nsIURI* aURI) const;
159   already_AddRefed<nsIURI> ResolveLocalRef(nsIContent* aContent) const;
160 
161   // Serializes mURI as a computed URI value, taking into account mIsLocalRef
162   // and serializing just the fragment if true.
163   void GetSourceString(nsString& aRef) const;
164 
165   bool EqualsExceptRef(nsIURI* aURI) const;
166 
167   // Can only be called from the main thread. Returns this URL's UTF-16
168   // representation, converting and caching its value if necessary.
169   const nsString& GetUTF16String() const;
170   // Returns this URL's UTF-16 representation, converting if necessary.
171   nsString GetUTF16StringForAnyThread() const;
172 
173   bool IsStringEmpty() const;
174 
175  private:
176   // mURI stores the lazily resolved URI.  This may be null if the URI is
177   // invalid, even once resolved.
178   mutable PtrHandle<nsIURI> mURI;
179 
180  public:
181   RefPtr<URLExtraData> mExtraData;
182 
183  private:
184   // Returns a substring based on mStrings.mRustString which should not be
185   // exposed to external consumers.
186   nsDependentCSubstring GetRustString() const;
187 
188   mutable bool mURIResolved;
189   // mIsLocalRef is set when url starts with a U+0023 number sign(#) character.
190   mutable Maybe<bool> mIsLocalRef;
191   mutable Maybe<bool> mMightHaveRef;
192 
193   mutable union RustOrGeckoString {
RustOrGeckoString(const nsAString & aString)194     explicit RustOrGeckoString(const nsAString& aString) : mString(aString) {}
RustOrGeckoString(ServoRawOffsetArc<RustString> aString)195     explicit RustOrGeckoString(ServoRawOffsetArc<RustString> aString)
196         : mRustString(aString) {}
~RustOrGeckoString()197     ~RustOrGeckoString() {}
198     nsString mString;
199     mozilla::ServoRawOffsetArc<RustString> mRustString;
200   } mStrings;
201   mutable bool mUsingRustString;
202 
203  protected:
204   // Only used by ImageValue.  Declared up here because otherwise bindgen gets
205   // confused by the non-standard-layout packing of the variable up into
206   // URLValueData.
207   bool mLoadedImage = false;
208   const CORSMode mCORSMode;
209 
210   virtual ~URLValueData();
211 
212   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
213 
214  private:
215   URLValueData(const URLValueData& aOther) = delete;
216   URLValueData& operator=(const URLValueData& aOther) = delete;
217 
218   friend struct ImageValue;
219 };
220 
221 struct URLValue final : public URLValueData {
222   // These two constructors are safe to call only on the main thread.
223   URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
224            nsIPrincipal* aOriginPrincipal);
225   URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
226            nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal);
227 
228   // This constructor is safe to call from any thread.
URLValuefinal229   URLValue(ServoRawOffsetArc<RustString> aString,
230            already_AddRefed<URLExtraData> aExtraData)
231       : URLValueData(aString, Move(aExtraData), CORSMode::CORS_NONE) {}
232 
233   URLValue(const URLValue&) = delete;
234   URLValue& operator=(const URLValue&) = delete;
235 
236   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
237 };
238 
239 struct ImageValue final : public URLValueData {
240   static ImageValue* CreateFromURLValue(URLValue* url, nsIDocument* aDocument,
241                                         CORSMode aCORSMode);
242 
243   // Not making the constructor and destructor inline because that would
244   // force us to include imgIRequest.h, which leads to REQUIRES hell, since
245   // this header is included all over.
246   //
247   // This constructor is only safe to call from the main thread.
248   ImageValue(nsIURI* aURI, const nsAString& aString,
249              already_AddRefed<URLExtraData> aExtraData, nsIDocument* aDocument,
250              CORSMode aCORSMode);
251 
252   // This constructor is only safe to call from the main thread.
253   ImageValue(nsIURI* aURI, ServoRawOffsetArc<RustString> aString,
254              already_AddRefed<URLExtraData> aExtraData, nsIDocument* aDocument,
255              CORSMode aCORSMode);
256 
257   // This constructor is safe to call from any thread, but Initialize
258   // must be called later for the object to be useful.
259   ImageValue(const nsAString& aString,
260              already_AddRefed<URLExtraData> aExtraData, CORSMode aCORSMode);
261 
262   // This constructor is safe to call from any thread, but Initialize
263   // must be called later for the object to be useful.
264   ImageValue(ServoRawOffsetArc<RustString> aURIString,
265              already_AddRefed<URLExtraData> aExtraData, CORSMode aCORSMode);
266 
267   ImageValue(const ImageValue&) = delete;
268   ImageValue& operator=(const ImageValue&) = delete;
269 
270   void Initialize(nsIDocument* aDocument);
271 
272   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
273 
274  protected:
275   ~ImageValue();
276 
277  public:
278   // Inherit Equals from URLValueData
279 
280   nsRefPtrHashtable<nsPtrHashKey<nsIDocument>, imgRequestProxy> mRequests;
281 };
282 
283 struct GridNamedArea {
284   nsString mName;
285   uint32_t mColumnStart;
286   uint32_t mColumnEnd;
287   uint32_t mRowStart;
288   uint32_t mRowEnd;
289 };
290 
291 struct GridTemplateAreasValue final {
292   // Parsed value
293   nsTArray<GridNamedArea> mNamedAreas;
294 
295   // Original <string> values. Length gives the number of rows,
296   // content makes serialization easier.
297   nsTArray<nsString> mTemplates;
298 
299   // How many columns grid-template-areas contributes to the explicit grid.
300   // http://dev.w3.org/csswg/css-grid/#explicit-grid
301   uint32_t mNColumns;
302 
303   // How many rows grid-template-areas contributes to the explicit grid.
304   // http://dev.w3.org/csswg/css-grid/#explicit-grid
NRowsfinal305   uint32_t NRows() const { return mTemplates.Length(); }
306 
GridTemplateAreasValuefinal307   GridTemplateAreasValue()
308       : mNColumns(0)
309   // Default constructors for mNamedAreas and mTemplates: empty arrays.
310   {}
311 
312   bool operator==(const GridTemplateAreasValue& aOther) const {
313     return mTemplates == aOther.mTemplates;
314   }
315 
316   bool operator!=(const GridTemplateAreasValue& aOther) const {
317     return !(*this == aOther);
318   }
319 
320   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GridTemplateAreasValue)
321 
322   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
323 
324  private:
325   // Private destructor to make sure this isn't used as a stack variable
326   // or member variable.
~GridTemplateAreasValuefinal327   ~GridTemplateAreasValue() {}
328 
329   GridTemplateAreasValue(const GridTemplateAreasValue& aOther) = delete;
330   GridTemplateAreasValue& operator=(const GridTemplateAreasValue& aOther) =
331       delete;
332 };
333 
334 struct RGBAColorData {
335   // 1.0 means 100% for all components, but the value may fall outside
336   // the range of [0.0, 1.0], so it is necessary to clamp them when
337   // converting to nscolor.
338   float mR;
339   float mG;
340   float mB;
341   float mA;
342 
343   RGBAColorData() = default;
RGBAColorDataRGBAColorData344   MOZ_IMPLICIT RGBAColorData(nscolor aColor)
345       : mR(NS_GET_R(aColor) * (1.0f / 255.0f)),
346         mG(NS_GET_G(aColor) * (1.0f / 255.0f)),
347         mB(NS_GET_B(aColor) * (1.0f / 255.0f)),
348         mA(NS_GET_A(aColor) * (1.0f / 255.0f)) {}
RGBAColorDataRGBAColorData349   RGBAColorData(float aR, float aG, float aB, float aA)
350       : mR(aR), mG(aG), mB(aB), mA(aA) {}
351 
352   bool operator==(const RGBAColorData& aOther) const {
353     return mR == aOther.mR && mG == aOther.mG && mB == aOther.mB &&
354            mA == aOther.mA;
355   }
356   bool operator!=(const RGBAColorData& aOther) const {
357     return !(*this == aOther);
358   }
359 
ToColorRGBAColorData360   nscolor ToColor() const {
361     return NS_RGBA(ClampColor(mR * 255.0f), ClampColor(mG * 255.0f),
362                    ClampColor(mB * 255.0f), ClampColor(mA * 255.0f));
363   }
364 
WithAlphaRGBAColorData365   RGBAColorData WithAlpha(float aAlpha) const {
366     RGBAColorData result = *this;
367     result.mA = aAlpha;
368     return result;
369   }
370 };
371 
372 struct ComplexColorData {
373   RGBAColorData mColor;
374   float mForegroundRatio;
375 
376   ComplexColorData() = default;
ComplexColorDataComplexColorData377   ComplexColorData(const RGBAColorData& aColor, float aForegroundRatio)
378       : mColor(aColor), mForegroundRatio(aForegroundRatio) {}
ComplexColorDataComplexColorData379   ComplexColorData(nscolor aColor, float aForegroundRatio)
380       : mColor(aColor), mForegroundRatio(aForegroundRatio) {}
ComplexColorDataComplexColorData381   explicit ComplexColorData(const StyleComplexColor& aColor)
382       : mColor(aColor.mColor),
383         mForegroundRatio(aColor.mForegroundRatio * (1.0f / 255.0f)) {}
384 
385   bool operator==(const ComplexColorData& aOther) const {
386     return mForegroundRatio == aOther.mForegroundRatio &&
387            (IsCurrentColor() || mColor == aOther.mColor);
388   }
389   bool operator!=(const ComplexColorData& aOther) const {
390     return !(*this == aOther);
391   }
392 
IsCurrentColorComplexColorData393   bool IsCurrentColor() const { return mForegroundRatio >= 1.0f; }
IsNumericColorComplexColorData394   bool IsNumericColor() const { return mForegroundRatio <= 0.0f; }
395 
ToComplexColorComplexColorData396   StyleComplexColor ToComplexColor() const {
397     return {mColor.ToColor(), ClampColor(mForegroundRatio * 255.0f)};
398   }
399 };
400 
401 struct ComplexColorValue final : public ComplexColorData {
402   // Just redirect any parameter to the data struct.
403   template <typename... Args>
ComplexColorValuefinal404   explicit ComplexColorValue(Args&&... aArgs)
405       : ComplexColorData(Forward<Args>(aArgs)...) {}
406   ComplexColorValue(const ComplexColorValue&) = delete;
407 
408   NS_INLINE_DECL_REFCOUNTING(ComplexColorValue)
409 
410   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
411 
412  private:
~ComplexColorValuefinal413   ~ComplexColorValue() {}
414 };
415 
416 }  // namespace css
417 }  // namespace mozilla
418 
419 enum nsCSSUnit {
420   eCSSUnit_Null = 0,     // (n/a) null unit, value is not specified
421   eCSSUnit_Auto = 1,     // (n/a) value is algorithmic
422   eCSSUnit_Inherit = 2,  // (n/a) value is inherited
423   eCSSUnit_Initial = 3,  // (n/a) value is default UA value
424   eCSSUnit_Unset = 4,    // (n/a) value equivalent to 'initial' if on a reset
425                          // property, 'inherit' otherwise
426   eCSSUnit_None = 5,     // (n/a) value is none
427   eCSSUnit_Normal =
428       6,  // (n/a) value is normal (algorithmic, different than auto)
429   eCSSUnit_System_Font = 7,    // (n/a) value is -moz-use-system-font
430   eCSSUnit_All = 8,            // (n/a) value is all
431   eCSSUnit_Dummy = 9,          // (n/a) a fake but specified value, used
432                                //       only in temporary values
433   eCSSUnit_DummyInherit = 10,  // (n/a) a fake but specified value, used
434                                //       only in temporary values
435 
436   eCSSUnit_String = 11,       // (char16_t*) a string value
437   eCSSUnit_Ident = 12,        // (char16_t*) a string value
438   eCSSUnit_Attr = 14,         // (char16_t*) a attr(string) value
439   eCSSUnit_Local_Font = 15,   // (char16_t*) a local font name
440   eCSSUnit_Font_Format = 16,  // (char16_t*) a font format name
441   eCSSUnit_Element = 17,      // (char16_t*) an element id
442 
443   eCSSUnit_Array = 20,  // (nsCSSValue::Array*) a list of values
444   eCSSUnit_Counter =
445       21,  // (nsCSSValue::Array*) a counter(string,[string]) value
446   eCSSUnit_Counters =
447       22,  // (nsCSSValue::Array*) a counters(string,string[,string]) value
448   eCSSUnit_Cubic_Bezier = 23,  // (nsCSSValue::Array*) a list of float values
449   eCSSUnit_Steps = 24,  // (nsCSSValue::Array*) a list of (integer, enumerated)
450   eCSSUnit_Symbols =
451       25,  // (nsCSSValue::Array*) a symbols(enumerated, symbols) value
452   eCSSUnit_Function = 26,  // (nsCSSValue::Array*) a function with
453                            //  parameters.  First elem of array is name,
454                            //  an nsCSSKeyword as eCSSUnit_Enumerated,
455                            //  the rest of the values are arguments.
456 
457   // The top level of a calc() expression is eCSSUnit_Calc.  All
458   // remaining eCSSUnit_Calc_* units only occur inside these toplevel
459   // calc values.
460 
461   // eCSSUnit_Calc has an array with exactly 1 element.  eCSSUnit_Calc
462   // exists so we can distinguish calc(2em) from 2em as specified values
463   // (but we drop this distinction for nsStyleCoord when we store
464   // computed values).
465   eCSSUnit_Calc = 30,  // (nsCSSValue::Array*) calc() value
466   // Plus, Minus, Times_* and Divided have arrays with exactly 2
467   // elements.  a + b + c + d is grouped as ((a + b) + c) + d
468   eCSSUnit_Calc_Plus = 31,     // (nsCSSValue::Array*) + node within calc()
469   eCSSUnit_Calc_Minus = 32,    // (nsCSSValue::Array*) - within calc
470   eCSSUnit_Calc_Times_L = 33,  // (nsCSSValue::Array*) num * val within calc
471   eCSSUnit_Calc_Times_R = 34,  // (nsCSSValue::Array*) val * num within calc
472   eCSSUnit_Calc_Divided = 35,  // (nsCSSValue::Array*) / within calc
473 
474   eCSSUnit_URL = 40,                // (nsCSSValue::URL*) value
475   eCSSUnit_Image = 41,              // (nsCSSValue::Image*) value
476   eCSSUnit_Gradient = 42,           // (nsCSSValueGradient*) value
477   eCSSUnit_TokenStream = 43,        // (nsCSSValueTokenStream*) value
478   eCSSUnit_GridTemplateAreas = 44,  // (GridTemplateAreasValue*)
479                                     // for grid-template-areas
480 
481   eCSSUnit_Pair = 50,         // (nsCSSValuePair*) pair of values
482   eCSSUnit_Triplet = 51,      // (nsCSSValueTriplet*) triplet of values
483   eCSSUnit_Rect = 52,         // (nsCSSRect*) rectangle (four values)
484   eCSSUnit_List = 53,         // (nsCSSValueList*) list of values
485   eCSSUnit_ListDep = 54,      // (nsCSSValueList*) same as List
486                               //   but does not own the list
487   eCSSUnit_SharedList = 55,   // (nsCSSValueSharedList*) same as list
488                               //   but reference counted and shared
489   eCSSUnit_PairList = 56,     // (nsCSSValuePairList*) list of value pairs
490   eCSSUnit_PairListDep = 57,  // (nsCSSValuePairList*) same as PairList
491                               //   but does not own the list
492 
493   eCSSUnit_FontFamilyList = 58,  // (SharedFontList*) value
494 
495   // Atom units
496   eCSSUnit_AtomIdent = 60,  // (nsAtom*) for its string as an identifier
497 
498   eCSSUnit_Integer = 70,     // (int) simple value
499   eCSSUnit_Enumerated = 71,  // (int) value has enumerated meaning
500 
501   eCSSUnit_EnumColor = 80,  // (int) enumerated color (kColorKTable)
502   eCSSUnit_RGBColor = 81,   // (nscolor) an opaque RGBA value specified as rgb()
503   eCSSUnit_RGBAColor = 82,  // (nscolor) an RGBA value specified as rgba()
504   eCSSUnit_HexColor =
505       83,  // (nscolor) an opaque RGBA value specified as #rrggbb
506   eCSSUnit_ShortHexColor =
507       84,  // (nscolor) an opaque RGBA value specified as #rgb
508   eCSSUnit_HexColorAlpha =
509       85,  // (nscolor) an opaque RGBA value specified as #rrggbbaa
510   eCSSUnit_ShortHexColorAlpha =
511       86,  // (nscolor) an opaque RGBA value specified as #rgba
512   eCSSUnit_PercentageRGBColor = 87,   // (nsCSSValueFloatColor*) an opaque
513                                       // RGBA value specified as rgb() with
514                                       // percentage components. Values over
515                                       // 100% are allowed.
516   eCSSUnit_PercentageRGBAColor = 88,  // (nsCSSValueFloatColor*) an RGBA value
517                                       // specified as rgba() with percentage
518                                       // components. Values over 100% are
519                                       // allowed.
520   eCSSUnit_HSLColor = 89,             // (nsCSSValueFloatColor*)
521   eCSSUnit_HSLAColor = 90,            // (nsCSSValueFloatColor*)
522   eCSSUnit_ComplexColor = 91,         // (ComplexColorValue*)
523 
524   eCSSUnit_Percent =
525       100,  // (float) 1.0 == 100%) value is percentage of something
526   eCSSUnit_Number = 101,  // (float) value is numeric (usually multiplier,
527                           // different behavior than percent)
528 
529   // Length units - relative
530   // Viewport relative measure
531   eCSSUnit_ViewportWidth =
532       700,  // (float) 1% of the width of the initial containing block
533   eCSSUnit_ViewportHeight =
534       701,  // (float) 1% of the height of the initial containing block
535   eCSSUnit_ViewportMin =
536       702,  // (float) smaller of ViewportWidth and ViewportHeight
537   eCSSUnit_ViewportMax =
538       703,  // (float) larger of ViewportWidth and ViewportHeight
539 
540   // Font relative measure
541   eCSSUnit_EM = 800,  // (float) == current font size
542   eCSSUnit_XHeight =
543       801,  // (float) distance from top of lower case x to baseline
544   eCSSUnit_Char =
545       802,  // (float) number of characters, used for width with monospace font
546   eCSSUnit_RootEM = 803,  // (float) == root element font size
547 
548   // Screen relative measure
549   eCSSUnit_Point = 900,       // (float) 4/3 of a CSS pixel
550   eCSSUnit_Inch = 901,        // (float) 96 CSS pixels
551   eCSSUnit_Millimeter = 902,  // (float) 96/25.4 CSS pixels
552   eCSSUnit_Centimeter = 903,  // (float) 96/2.54 CSS pixels
553   eCSSUnit_Pica = 904,        // (float) 12 points == 16 CSS pixls
554   eCSSUnit_Quarter = 905,     // (float) 96/101.6 CSS pixels
555   eCSSUnit_Pixel = 906,       // (float) CSS pixel unit
556 
557   // Angular units
558   eCSSUnit_Degree = 1000,  // (float) 360 per circle
559   eCSSUnit_Grad = 1001,    // (float) 400 per circle
560   eCSSUnit_Radian = 1002,  // (float) 2*pi per circle
561   eCSSUnit_Turn = 1003,    // (float) 1 per circle
562 
563   // Frequency units
564   eCSSUnit_Hertz = 2000,      // (float) 1/seconds
565   eCSSUnit_Kilohertz = 2001,  // (float) 1000 Hertz
566 
567   // Time units
568   eCSSUnit_Seconds = 3000,       // (float) Standard time
569   eCSSUnit_Milliseconds = 3001,  // (float) 1/1000 second
570 
571   // Flexible fraction (CSS Grid)
572   eCSSUnit_FlexFraction = 4000  // (float) Fraction of free space
573 };
574 
575 struct nsCSSValueGradient;
576 struct nsCSSValuePair;
577 struct nsCSSValuePair_heap;
578 struct nsCSSValueTokenStream;
579 struct nsCSSRect;
580 struct nsCSSRect_heap;
581 struct nsCSSValueList;
582 struct nsCSSValueList_heap;
583 struct nsCSSValueSharedList;
584 struct nsCSSValuePairList;
585 struct nsCSSValuePairList_heap;
586 struct nsCSSValueTriplet;
587 struct nsCSSValueTriplet_heap;
588 class nsCSSValueFloatColor;
589 
590 class nsCSSValue {
591  public:
592   struct Array;
593   friend struct Array;
594 
595   friend struct mozilla::css::URLValueData;
596 
597   friend struct mozilla::css::ImageValue;
598 
599   // for valueless units only (null, auto, inherit, none, all, normal)
mUnit(aUnit)600   explicit nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null) : mUnit(aUnit) {
601     MOZ_ASSERT(aUnit <= eCSSUnit_DummyInherit, "not a valueless unit");
602   }
603 
604   nsCSSValue(int32_t aValue, nsCSSUnit aUnit);
605   nsCSSValue(float aValue, nsCSSUnit aUnit);
606   nsCSSValue(const nsString& aValue, nsCSSUnit aUnit);
607   nsCSSValue(Array* aArray, nsCSSUnit aUnit);
608   explicit nsCSSValue(mozilla::css::URLValue* aValue);
609   explicit nsCSSValue(mozilla::css::ImageValue* aValue);
610   explicit nsCSSValue(nsCSSValueGradient* aValue);
611   explicit nsCSSValue(nsCSSValueTokenStream* aValue);
612   explicit nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue);
613   explicit nsCSSValue(mozilla::SharedFontList* aValue);
614   nsCSSValue(const nsCSSValue& aCopy);
nsCSSValue(nsCSSValue && aOther)615   nsCSSValue(nsCSSValue&& aOther) : mUnit(aOther.mUnit), mValue(aOther.mValue) {
616     aOther.mUnit = eCSSUnit_Null;
617   }
618   template <typename T,
619             typename = typename std::enable_if<std::is_enum<T>::value>::type>
nsCSSValue(T aValue)620   explicit nsCSSValue(T aValue) : mUnit(eCSSUnit_Enumerated) {
621     static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
622                   "aValue must be an enum that fits within mValue.mInt");
623     mValue.mInt = static_cast<int32_t>(aValue);
624   }
625 
~nsCSSValue()626   ~nsCSSValue() { Reset(); }
627 
628   nsCSSValue& operator=(const nsCSSValue& aCopy);
629   nsCSSValue& operator=(nsCSSValue&& aCopy);
630   bool operator==(const nsCSSValue& aOther) const;
631 
632   bool operator!=(const nsCSSValue& aOther) const { return !(*this == aOther); }
633 
634   /**
635    * Serialize |this| as a specified value for |aProperty| and append
636    * it to |aResult|.
637    */
638   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
639 
GetUnit()640   nsCSSUnit GetUnit() const { return mUnit; }
IsLengthUnit()641   bool IsLengthUnit() const {
642     return eCSSUnit_ViewportWidth <= mUnit && mUnit <= eCSSUnit_Pixel;
643   }
IsLengthPercentCalcUnit()644   bool IsLengthPercentCalcUnit() const {
645     return IsLengthUnit() || mUnit == eCSSUnit_Percent || IsCalcUnit();
646   }
647   /**
648    * What the spec calls relative length units is, for us, split
649    * between relative length units and pixel length units.
650    *
651    * A "relative" length unit is a multiple of some derived metric,
652    * such as a font em-size, which itself was controlled by an input CSS
653    * length. Relative length units should not be scaled by zooming, since
654    * the underlying CSS length would already have been scaled.
655    */
IsRelativeLengthUnit()656   bool IsRelativeLengthUnit() const {
657     return eCSSUnit_EM <= mUnit && mUnit <= eCSSUnit_RootEM;
658   }
659   /**
660    * A "pixel" length unit is a some multiple of CSS pixels.
661    */
IsPixelLengthUnit(nsCSSUnit aUnit)662   static bool IsPixelLengthUnit(nsCSSUnit aUnit) {
663     return eCSSUnit_Point <= aUnit && aUnit <= eCSSUnit_Pixel;
664   }
IsPixelLengthUnit()665   bool IsPixelLengthUnit() const { return IsPixelLengthUnit(mUnit); }
IsPercentLengthUnit(nsCSSUnit aUnit)666   static bool IsPercentLengthUnit(nsCSSUnit aUnit) {
667     return aUnit == eCSSUnit_Percent;
668   }
IsPercentLengthUnit()669   bool IsPercentLengthUnit() { return IsPercentLengthUnit(mUnit); }
IsFloatUnit(nsCSSUnit aUnit)670   static bool IsFloatUnit(nsCSSUnit aUnit) { return eCSSUnit_Number <= aUnit; }
IsAngularUnit()671   bool IsAngularUnit() const {
672     return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn;
673   }
IsFrequencyUnit()674   bool IsFrequencyUnit() const {
675     return eCSSUnit_Hertz <= mUnit && mUnit <= eCSSUnit_Kilohertz;
676   }
IsTimeUnit()677   bool IsTimeUnit() const {
678     return eCSSUnit_Seconds <= mUnit && mUnit <= eCSSUnit_Milliseconds;
679   }
IsCalcUnit()680   bool IsCalcUnit() const {
681     return eCSSUnit_Calc <= mUnit && mUnit <= eCSSUnit_Calc_Divided;
682   }
683 
UnitHasStringValue()684   bool UnitHasStringValue() const {
685     return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Element;
686   }
UnitHasArrayValue()687   bool UnitHasArrayValue() const {
688     return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided;
689   }
690 
691   // Checks for the nsCSSValue being of a particular type of color unit:
692   //
693   //   - IsIntegerColorUnit returns true for:
694   //       eCSSUnit_RGBColor             -- rgb(int,int,int)
695   //       eCSSUnit_RGBAColor            -- rgba(int,int,int,float)
696   //       eCSSUnit_HexColor             -- #rrggbb
697   //       eCSSUnit_ShortHexColor        -- #rgb
698   //       eCSSUnit_HexColorAlpha        -- #rrggbbaa
699   //       eCSSUnit_ShortHexColorAlpha   -- #rgba
700   //
701   //   - IsFloatColorUnit returns true for:
702   //       eCSSUnit_PercentageRGBColor   -- rgb(%,%,%)
703   //       eCSSUnit_PercentageRGBAColor  -- rgba(%,%,%,float)
704   //       eCSSUnit_HSLColor             -- hsl(float,%,%)
705   //       eCSSUnit_HSLAColor            -- hsla(float,%,%,float)
706   //
707   //   - IsNumericColorUnit returns true for any of the above units.
708   //
709   // Note that color keywords and system colors are represented by
710   // eCSSUnit_EnumColor and eCSSUnit_Ident.
IsIntegerColorUnit()711   bool IsIntegerColorUnit() const { return IsIntegerColorUnit(mUnit); }
IsFloatColorUnit()712   bool IsFloatColorUnit() const { return IsFloatColorUnit(mUnit); }
IsNumericColorUnit()713   bool IsNumericColorUnit() const { return IsNumericColorUnit(mUnit); }
IsIntegerColorUnit(nsCSSUnit aUnit)714   static bool IsIntegerColorUnit(nsCSSUnit aUnit) {
715     return eCSSUnit_RGBColor <= aUnit && aUnit <= eCSSUnit_ShortHexColorAlpha;
716   }
IsFloatColorUnit(nsCSSUnit aUnit)717   static bool IsFloatColorUnit(nsCSSUnit aUnit) {
718     return eCSSUnit_PercentageRGBColor <= aUnit && aUnit <= eCSSUnit_HSLAColor;
719   }
IsNumericColorUnit(nsCSSUnit aUnit)720   static bool IsNumericColorUnit(nsCSSUnit aUnit) {
721     return IsIntegerColorUnit(aUnit) || IsFloatColorUnit(aUnit);
722   }
723 
GetIntValue()724   int32_t GetIntValue() const {
725     MOZ_ASSERT(mUnit == eCSSUnit_Integer || mUnit == eCSSUnit_Enumerated ||
726                    mUnit == eCSSUnit_EnumColor,
727                "not an int value");
728     return mValue.mInt;
729   }
730 
GetKeywordValue()731   nsCSSKeyword GetKeywordValue() const {
732     MOZ_ASSERT(mUnit == eCSSUnit_Enumerated, "not a keyword value");
733     return static_cast<nsCSSKeyword>(mValue.mInt);
734   }
735 
GetPercentValue()736   float GetPercentValue() const {
737     MOZ_ASSERT(mUnit == eCSSUnit_Percent, "not a percent value");
738     return mValue.mFloat;
739   }
740 
GetFloatValue()741   float GetFloatValue() const {
742     MOZ_ASSERT(eCSSUnit_Number <= mUnit, "not a float value");
743     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
744     return mValue.mFloat;
745   }
746 
GetAngleValue()747   float GetAngleValue() const {
748     MOZ_ASSERT(eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn,
749                "not an angle value");
750     return mValue.mFloat;
751   }
752 
753   // Converts any angle to radians.
754   double GetAngleValueInRadians() const;
755 
756   // Converts any angle to degrees.
757   double GetAngleValueInDegrees() const;
758 
GetStringValue(nsAString & aBuffer)759   nsAString& GetStringValue(nsAString& aBuffer) const {
760     MOZ_ASSERT(UnitHasStringValue(), "not a string value");
761     aBuffer.Truncate();
762     uint32_t len = NS_strlen(GetBufferValue(mValue.mString));
763     mValue.mString->ToString(len, aBuffer);
764     return aBuffer;
765   }
766 
GetStringBufferValue()767   const char16_t* GetStringBufferValue() const {
768     MOZ_ASSERT(UnitHasStringValue(), "not a string value");
769     return GetBufferValue(mValue.mString);
770   }
771 
772   nscolor GetColorValue() const;
773   bool IsNonTransparentColor() const;
GetStyleComplexColorValue()774   mozilla::StyleComplexColor GetStyleComplexColorValue() const {
775     MOZ_ASSERT(mUnit == eCSSUnit_ComplexColor);
776     return mValue.mComplexColor->ToComplexColor();
777   }
778 
GetArrayValue()779   Array* GetArrayValue() const {
780     MOZ_ASSERT(UnitHasArrayValue(), "not an array value");
781     return mValue.mArray;
782   }
783 
GetURLValue()784   nsIURI* GetURLValue() const {
785     MOZ_ASSERT(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
786                "not a URL value");
787     return mUnit == eCSSUnit_URL ? mValue.mURL->GetURI()
788                                  : mValue.mImage->GetURI();
789   }
790 
GetGradientValue()791   nsCSSValueGradient* GetGradientValue() const {
792     MOZ_ASSERT(mUnit == eCSSUnit_Gradient, "not a gradient value");
793     return mValue.mGradient;
794   }
795 
GetTokenStreamValue()796   nsCSSValueTokenStream* GetTokenStreamValue() const {
797     MOZ_ASSERT(mUnit == eCSSUnit_TokenStream, "not a token stream value");
798     return mValue.mTokenStream;
799   }
800 
GetSharedListValue()801   nsCSSValueSharedList* GetSharedListValue() const {
802     MOZ_ASSERT(mUnit == eCSSUnit_SharedList, "not a shared list value");
803     return mValue.mSharedList;
804   }
805 
GetFontFamilyListValue()806   mozilla::NotNull<mozilla::SharedFontList*> GetFontFamilyListValue() const {
807     MOZ_ASSERT(mUnit == eCSSUnit_FontFamilyList,
808                "not a font family list value");
809     NS_ASSERTION(mValue.mFontFamilyList != nullptr,
810                  "font family list value should never be null");
811     return mozilla::WrapNotNull(mValue.mFontFamilyList);
812   }
813 
814   // bodies of these are below
815   inline nsCSSValuePair& GetPairValue();
816   inline const nsCSSValuePair& GetPairValue() const;
817 
818   inline nsCSSRect& GetRectValue();
819   inline const nsCSSRect& GetRectValue() const;
820 
821   inline nsCSSValueList* GetListValue();
822   inline const nsCSSValueList* GetListValue() const;
823 
824   inline nsCSSValuePairList* GetPairListValue();
825   inline const nsCSSValuePairList* GetPairListValue() const;
826 
827   inline nsCSSValueTriplet& GetTripletValue();
828   inline const nsCSSValueTriplet& GetTripletValue() const;
829 
GetURLStructValue()830   mozilla::css::URLValue* GetURLStructValue() const {
831     // Not allowing this for Image values, because if the caller takes
832     // a ref to them they won't be able to delete them properly.
833     MOZ_ASSERT(mUnit == eCSSUnit_URL, "not a URL value");
834     return mValue.mURL;
835   }
836 
GetImageStructValue()837   mozilla::css::ImageValue* GetImageStructValue() const {
838     MOZ_ASSERT(mUnit == eCSSUnit_Image, "not an Image value");
839     return mValue.mImage;
840   }
841 
GetGridTemplateAreas()842   mozilla::css::GridTemplateAreasValue* GetGridTemplateAreas() const {
843     MOZ_ASSERT(mUnit == eCSSUnit_GridTemplateAreas,
844                "not a grid-template-areas value");
845     return mValue.mGridTemplateAreas;
846   }
847 
GetOriginalURLValue()848   const char16_t* GetOriginalURLValue() const {
849     MOZ_ASSERT(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
850                "not a URL value");
851     return mUnit == eCSSUnit_URL ? mValue.mURL->GetUTF16String().get()
852                                  : mValue.mImage->GetUTF16String().get();
853   }
854 
855   // Not making this inline because that would force us to include
856   // imgIRequest.h, which leads to REQUIRES hell, since this header is included
857   // all over.
858   imgRequestProxy* GetImageValue(nsIDocument* aDocument) const;
859 
860   // Like GetImageValue, but additionally will pass the imgRequestProxy
861   // through nsContentUtils::GetStaticRequest if aPresContent is static.
862   already_AddRefed<imgRequestProxy> GetPossiblyStaticImageValue(
863       nsIDocument* aDocument, nsPresContext* aPresContext) const;
864 
865   nscoord GetPixelLength() const;
866 
GetFloatColorValue()867   nsCSSValueFloatColor* GetFloatColorValue() const {
868     MOZ_ASSERT(IsFloatColorUnit(), "not a float color value");
869     return mValue.mFloatColor;
870   }
871 
GetAtomValue()872   nsAtom* GetAtomValue() const {
873     MOZ_ASSERT(mUnit == eCSSUnit_AtomIdent);
874     return mValue.mAtom;
875   }
876 
Reset()877   void Reset()  // sets to null
878   {
879     if (mUnit != eCSSUnit_Null) DoReset();
880   }
881 
882  private:
883   void DoReset();
884 
885  public:
886   void SetIntValue(int32_t aValue, nsCSSUnit aUnit);
887   template <typename T,
888             typename = typename std::enable_if<std::is_enum<T>::value>::type>
SetEnumValue(T aValue)889   void SetEnumValue(T aValue) {
890     static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
891                   "aValue must be an enum that fits within mValue.mInt");
892     SetIntValue(static_cast<int32_t>(aValue), eCSSUnit_Enumerated);
893   }
894   void SetPercentValue(float aValue);
895   void SetFloatValue(float aValue, nsCSSUnit aUnit);
896   void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
897   void SetAtomIdentValue(already_AddRefed<nsAtom> aValue);
898   void SetColorValue(nscolor aValue);
899   void SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit);
900   // converts the nscoord to pixels
901   void SetIntegerCoordValue(nscoord aCoord);
902   void SetFloatColorValue(float aComponent1, float aComponent2,
903                           float aComponent3, float aAlpha, nsCSSUnit aUnit);
904   void SetRGBAColorValue(const mozilla::css::RGBAColorData& aValue);
905   void SetComplexColorValue(
906       already_AddRefed<mozilla::css::ComplexColorValue> aValue);
907   void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
908   void SetURLValue(mozilla::css::URLValue* aURI);
909   void SetImageValue(mozilla::css::ImageValue* aImage);
910   void SetGradientValue(nsCSSValueGradient* aGradient);
911   void SetTokenStreamValue(nsCSSValueTokenStream* aTokenStream);
912   void SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue);
913   void SetFontFamilyListValue(
914       already_AddRefed<mozilla::SharedFontList> aFontListValue);
915   void SetPairValue(const nsCSSValuePair* aPair);
916   void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
917   void SetSharedListValue(nsCSSValueSharedList* aList);
918   void SetDependentListValue(nsCSSValueList* aList);
919   void SetDependentPairListValue(nsCSSValuePairList* aList);
920   void SetTripletValue(const nsCSSValueTriplet* aTriplet);
921   void SetTripletValue(const nsCSSValue& xValue, const nsCSSValue& yValue,
922                        const nsCSSValue& zValue);
923   void SetAutoValue();
924   void SetInheritValue();
925   void SetInitialValue();
926   void SetUnsetValue();
927   void SetNoneValue();
928   void SetAllValue();
929   void SetNormalValue();
930   void SetSystemFontValue();
931   void SetDummyValue();
932   void SetDummyInheritValue();
933 
934   // Converts an nsStyleCoord::CalcValue back into a CSSValue
935   void SetCalcValue(const nsStyleCoord::CalcValue* aCalc);
936 
937   nsStyleCoord::CalcValue GetCalcValue() const;
938 
939   // These are a little different - they allocate storage for you and
940   // return a handle.
941   nsCSSRect& SetRectValue();
942   nsCSSValueList* SetListValue();
943   nsCSSValuePairList* SetPairListValue();
944 
945   // These take ownership of the passed-in resource.
946   void AdoptListValue(mozilla::UniquePtr<nsCSSValueList> aValue);
947   void AdoptPairListValue(mozilla::UniquePtr<nsCSSValuePairList> aValue);
948 
949   void StartImageLoad(nsIDocument* aDocument,
950                       mozilla::CORSMode aCORSMode) const;  // Only pretend const
951 
952   // Initializes as a function value with the specified function id.
953   Array* InitFunction(nsCSSKeyword aFunctionId, uint32_t aNumArgs);
954   // Checks if this is a function value with the specified function id.
955   bool EqualsFunction(nsCSSKeyword aFunctionId) const;
956 
957   // Returns an already addrefed buffer.  Guaranteed to return non-null.
958   // (Will abort on allocation failure.)
959   static already_AddRefed<nsStringBuffer> BufferFromString(
960       const nsString& aValue);
961 
962   // Convert the given Ident value into AtomIdent.
963   void AtomizeIdentValue();
964 
965   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
966 
967   static void AppendSidesShorthandToString(const nsCSSPropertyID aProperties[],
968                                            const nsCSSValue* aValues[],
969                                            nsAString& aString);
970   static void AppendBasicShapeRadiusToString(
971       const nsCSSPropertyID aProperties[], const nsCSSValue* aValues[],
972       nsAString& aResult);
973   static void AppendAlignJustifyValueToString(int32_t aValue,
974                                               nsAString& aResult);
975 
976  private:
GetBufferValue(nsStringBuffer * aBuffer)977   static const char16_t* GetBufferValue(nsStringBuffer* aBuffer) {
978     return static_cast<char16_t*>(aBuffer->Data());
979   }
980 
981   void AppendPolygonToString(nsCSSPropertyID aProperty,
982                              nsAString& aResult) const;
983   void AppendPositionCoordinateToString(const nsCSSValue& aValue,
984                                         nsCSSPropertyID aProperty,
985                                         nsAString& aResult) const;
986   void AppendCircleOrEllipseToString(nsCSSKeyword aFunctionId,
987                                      nsCSSPropertyID aProperty,
988                                      nsAString& aResult) const;
989   void AppendBasicShapePositionToString(nsAString& aResult) const;
990   void AppendInsetToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
991 
992  protected:
993   nsCSSUnit mUnit;
994   union {
995     int32_t mInt;
996     float mFloat;
997     // Note: the capacity of the buffer may exceed the length of the string.
998     // If we're of a string type, mString is not null.
999     nsStringBuffer* MOZ_OWNING_REF mString;
1000     nscolor mColor;
1001     nsAtom* MOZ_OWNING_REF mAtom;
1002     Array* MOZ_OWNING_REF mArray;
1003     mozilla::css::URLValue* MOZ_OWNING_REF mURL;
1004     mozilla::css::ImageValue* MOZ_OWNING_REF mImage;
1005     mozilla::css::GridTemplateAreasValue* MOZ_OWNING_REF mGridTemplateAreas;
1006     nsCSSValueGradient* MOZ_OWNING_REF mGradient;
1007     nsCSSValueTokenStream* MOZ_OWNING_REF mTokenStream;
1008     nsCSSValuePair_heap* MOZ_OWNING_REF mPair;
1009     nsCSSRect_heap* MOZ_OWNING_REF mRect;
1010     nsCSSValueTriplet_heap* MOZ_OWNING_REF mTriplet;
1011     nsCSSValueList_heap* MOZ_OWNING_REF mList;
1012     nsCSSValueList* mListDependent;
1013     nsCSSValueSharedList* MOZ_OWNING_REF mSharedList;
1014     nsCSSValuePairList_heap* MOZ_OWNING_REF mPairList;
1015     nsCSSValuePairList* mPairListDependent;
1016     nsCSSValueFloatColor* MOZ_OWNING_REF mFloatColor;
1017     mozilla::SharedFontList* MOZ_OWNING_REF mFontFamilyList;
1018     mozilla::css::ComplexColorValue* MOZ_OWNING_REF mComplexColor;
1019   } mValue;
1020 };
1021 
1022 struct nsCSSValue::Array final {
1023   // return |Array| with reference count of zero
Createfinal1024   static Array* Create(size_t aItemCount) {
1025     return new (aItemCount) Array(aItemCount);
1026   }
1027 
1028   nsCSSValue& operator[](size_t aIndex) {
1029     MOZ_ASSERT(aIndex < mCount, "out of range");
1030     return mArray[aIndex];
1031   }
1032 
1033   const nsCSSValue& operator[](size_t aIndex) const {
1034     MOZ_ASSERT(aIndex < mCount, "out of range");
1035     return mArray[aIndex];
1036   }
1037 
Itemfinal1038   nsCSSValue& Item(size_t aIndex) { return (*this)[aIndex]; }
Itemfinal1039   const nsCSSValue& Item(size_t aIndex) const { return (*this)[aIndex]; }
1040 
Countfinal1041   size_t Count() const { return mCount; }
1042 
1043   // callers depend on the items being contiguous
ItemStoragefinal1044   nsCSSValue* ItemStorage() { return this->First(); }
1045 
1046   bool operator==(const Array& aOther) const {
1047     if (mCount != aOther.mCount) return false;
1048     for (size_t i = 0; i < mCount; ++i)
1049       if ((*this)[i] != aOther[i]) return false;
1050     return true;
1051   }
1052 
1053   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Array);
1054 
1055  private:
1056   const size_t mCount;
1057   // This must be the last sub-object, since we extend this array to
1058   // be of size mCount; it needs to be a sub-object so it gets proper
1059   // alignment.
1060   nsCSSValue mArray[1];
1061 
newfinal1062   void* operator new(size_t aSelfSize, size_t aItemCount) CPP_THROW_NEW {
1063     MOZ_ASSERT(aItemCount > 0, "cannot have a 0 item count");
1064     return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1));
1065   }
1066 
deletefinal1067   void operator delete(void* aPtr) { ::operator delete(aPtr); }
1068 
Firstfinal1069   nsCSSValue* First() { return mArray; }
1070 
Firstfinal1071   const nsCSSValue* First() const { return mArray; }
1072 
1073 #define CSSVALUE_LIST_FOR_EXTRA_VALUES(var)                          \
1074   for (nsCSSValue* var = First() + 1, *var##_end = First() + mCount; \
1075        var != var##_end; ++var)
1076 
Arrayfinal1077   explicit Array(size_t aItemCount) : mRefCnt(0), mCount(aItemCount) {
1078     CSSVALUE_LIST_FOR_EXTRA_VALUES(val) { new (val) nsCSSValue(); }
1079   }
1080 
~Arrayfinal1081   ~Array() {
1082     CSSVALUE_LIST_FOR_EXTRA_VALUES(val) { val->~nsCSSValue(); }
1083   }
1084 
1085   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1086 
1087 #undef CSSVALUE_LIST_FOR_EXTRA_VALUES
1088 
1089  private:
1090   Array(const Array& aOther) = delete;
1091   Array& operator=(const Array& aOther) = delete;
1092 };
1093 
1094 // Prefer nsCSSValue::Array for lists of fixed size.
1095 struct nsCSSValueList {
nsCSSValueListnsCSSValueList1096   nsCSSValueList() : mNext(nullptr) { MOZ_COUNT_CTOR(nsCSSValueList); }
1097   ~nsCSSValueList();
1098 
1099   nsCSSValueList* Clone() const;  // makes a deep copy. Infallible.
1100   void CloneInto(nsCSSValueList* aList) const;  // makes a deep copy into aList
1101   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
1102 
1103   static bool Equal(const nsCSSValueList* aList1, const nsCSSValueList* aList2);
1104 
1105   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1106 
1107   nsCSSValue mValue;
1108   nsCSSValueList* mNext;
1109 
1110  private:
nsCSSValueListnsCSSValueList1111   nsCSSValueList(const nsCSSValueList& aCopy)  // makes a shallow copy
1112       : mValue(aCopy.mValue), mNext(nullptr) {
1113     MOZ_COUNT_CTOR(nsCSSValueList);
1114   }
1115 
1116   // We don't want operator== or operator!= because they wouldn't be
1117   // null-safe, which is generally what we need.  Use |Equal| method
1118   // above instead.
1119   bool operator==(nsCSSValueList const& aOther) const = delete;
1120   bool operator!=(const nsCSSValueList& aOther) const = delete;
1121 };
1122 
1123 // nsCSSValueList_heap differs from nsCSSValueList only in being
1124 // refcounted.  It should not be necessary to use this class directly;
1125 // it's an implementation detail of nsCSSValue.
1126 struct nsCSSValueList_heap final : public nsCSSValueList {
1127   NS_INLINE_DECL_REFCOUNTING(nsCSSValueList_heap)
1128 
1129   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1130 
1131  private:
1132   // Private destructor, to discourage deletion outside of Release():
~nsCSSValueList_heapfinal1133   ~nsCSSValueList_heap() {}
1134 };
1135 
1136 // This is a reference counted list value.  Note that the object is
1137 // a wrapper for the reference count and a pointer to the head of the
1138 // list, whereas the other list types (such as nsCSSValueList) do
1139 // not have such a wrapper.
1140 struct nsCSSValueSharedList final {
nsCSSValueSharedListfinal1141   nsCSSValueSharedList() : mHead(nullptr) {}
1142 
1143   // Takes ownership of aList.
nsCSSValueSharedListfinal1144   explicit nsCSSValueSharedList(nsCSSValueList* aList) : mHead(aList) {}
1145 
1146  private:
1147   // Private destructor, to discourage deletion outside of Release():
1148   ~nsCSSValueSharedList();
1149 
1150  public:
1151   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSValueSharedList)
1152 
1153   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
1154 
1155   bool operator==(nsCSSValueSharedList const& aOther) const;
1156   bool operator!=(const nsCSSValueSharedList& aOther) const {
1157     return !(*this == aOther);
1158   }
1159 
1160   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1161 
1162   nsCSSValueList* mHead;
1163 };
1164 
1165 // This has to be here so that the relationship between nsCSSValueList
1166 // and nsCSSValueList_heap is visible.
GetListValue()1167 inline nsCSSValueList* nsCSSValue::GetListValue() {
1168   if (mUnit == eCSSUnit_List)
1169     return mValue.mList;
1170   else {
1171     MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a list value");
1172     return mValue.mListDependent;
1173   }
1174 }
1175 
GetListValue()1176 inline const nsCSSValueList* nsCSSValue::GetListValue() const {
1177   if (mUnit == eCSSUnit_List)
1178     return mValue.mList;
1179   else {
1180     MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a list value");
1181     return mValue.mListDependent;
1182   }
1183 }
1184 
1185 struct nsCSSRect {
1186   nsCSSRect(void);
1187   nsCSSRect(const nsCSSRect& aCopy);
1188   ~nsCSSRect();
1189 
1190   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
1191 
1192   bool operator==(const nsCSSRect& aOther) const {
1193     return mTop == aOther.mTop && mRight == aOther.mRight &&
1194            mBottom == aOther.mBottom && mLeft == aOther.mLeft;
1195   }
1196 
1197   bool operator!=(const nsCSSRect& aOther) const {
1198     return mTop != aOther.mTop || mRight != aOther.mRight ||
1199            mBottom != aOther.mBottom || mLeft != aOther.mLeft;
1200   }
1201 
1202   void SetAllSidesTo(const nsCSSValue& aValue);
1203 
AllSidesEqualTonsCSSRect1204   bool AllSidesEqualTo(const nsCSSValue& aValue) const {
1205     return mTop == aValue && mRight == aValue && mBottom == aValue &&
1206            mLeft == aValue;
1207   }
1208 
ResetnsCSSRect1209   void Reset() {
1210     mTop.Reset();
1211     mRight.Reset();
1212     mBottom.Reset();
1213     mLeft.Reset();
1214   }
1215 
HasValuensCSSRect1216   bool HasValue() const {
1217     return mTop.GetUnit() != eCSSUnit_Null ||
1218            mRight.GetUnit() != eCSSUnit_Null ||
1219            mBottom.GetUnit() != eCSSUnit_Null ||
1220            mLeft.GetUnit() != eCSSUnit_Null;
1221   }
1222 
1223   nsCSSValue mTop;
1224   nsCSSValue mRight;
1225   nsCSSValue mBottom;
1226   nsCSSValue mLeft;
1227 
1228   typedef nsCSSValue nsCSSRect::*side_type;
1229   static const side_type sides[4];
1230 };
1231 
1232 // nsCSSRect_heap differs from nsCSSRect only in being
1233 // refcounted.  It should not be necessary to use this class directly;
1234 // it's an implementation detail of nsCSSValue.
1235 struct nsCSSRect_heap final : public nsCSSRect {
1236   NS_INLINE_DECL_REFCOUNTING(nsCSSRect_heap)
1237 
1238   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1239 
1240  private:
1241   // Private destructor, to discourage deletion outside of Release():
~nsCSSRect_heapfinal1242   ~nsCSSRect_heap() {}
1243 };
1244 
1245 // This has to be here so that the relationship between nsCSSRect
1246 // and nsCSSRect_heap is visible.
GetRectValue()1247 inline nsCSSRect& nsCSSValue::GetRectValue() {
1248   MOZ_ASSERT(mUnit == eCSSUnit_Rect, "not a rect value");
1249   return *mValue.mRect;
1250 }
1251 
GetRectValue()1252 inline const nsCSSRect& nsCSSValue::GetRectValue() const {
1253   MOZ_ASSERT(mUnit == eCSSUnit_Rect, "not a rect value");
1254   return *mValue.mRect;
1255 }
1256 
1257 struct nsCSSValuePair {
nsCSSValuePairnsCSSValuePair1258   nsCSSValuePair() { MOZ_COUNT_CTOR(nsCSSValuePair); }
nsCSSValuePairnsCSSValuePair1259   explicit nsCSSValuePair(nsCSSUnit aUnit) : mXValue(aUnit), mYValue(aUnit) {
1260     MOZ_COUNT_CTOR(nsCSSValuePair);
1261   }
nsCSSValuePairnsCSSValuePair1262   nsCSSValuePair(const nsCSSValue& aXValue, const nsCSSValue& aYValue)
1263       : mXValue(aXValue), mYValue(aYValue) {
1264     MOZ_COUNT_CTOR(nsCSSValuePair);
1265   }
nsCSSValuePairnsCSSValuePair1266   nsCSSValuePair(const nsCSSValuePair& aCopy)
1267       : mXValue(aCopy.mXValue), mYValue(aCopy.mYValue) {
1268     MOZ_COUNT_CTOR(nsCSSValuePair);
1269   }
~nsCSSValuePairnsCSSValuePair1270   ~nsCSSValuePair() { MOZ_COUNT_DTOR(nsCSSValuePair); }
1271 
1272   nsCSSValuePair& operator=(const nsCSSValuePair& aOther) {
1273     mXValue = aOther.mXValue;
1274     mYValue = aOther.mYValue;
1275     return *this;
1276   }
1277 
1278   bool operator==(const nsCSSValuePair& aOther) const {
1279     return mXValue == aOther.mXValue && mYValue == aOther.mYValue;
1280   }
1281 
1282   bool operator!=(const nsCSSValuePair& aOther) const {
1283     return mXValue != aOther.mXValue || mYValue != aOther.mYValue;
1284   }
1285 
BothValuesEqualTonsCSSValuePair1286   bool BothValuesEqualTo(const nsCSSValue& aValue) const {
1287     return mXValue == aValue && mYValue == aValue;
1288   }
1289 
SetBothValuesTonsCSSValuePair1290   void SetBothValuesTo(const nsCSSValue& aValue) {
1291     mXValue = aValue;
1292     mYValue = aValue;
1293   }
1294 
ResetnsCSSValuePair1295   void Reset() {
1296     mXValue.Reset();
1297     mYValue.Reset();
1298   }
1299 
HasValuensCSSValuePair1300   bool HasValue() const {
1301     return mXValue.GetUnit() != eCSSUnit_Null ||
1302            mYValue.GetUnit() != eCSSUnit_Null;
1303   }
1304 
1305   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
1306 
1307   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1308 
1309   nsCSSValue mXValue;
1310   nsCSSValue mYValue;
1311 };
1312 
1313 // nsCSSValuePair_heap differs from nsCSSValuePair only in being
1314 // refcounted.  It should not be necessary to use this class directly;
1315 // it's an implementation detail of nsCSSValue.
1316 struct nsCSSValuePair_heap final : public nsCSSValuePair {
1317   // forward constructor
nsCSSValuePair_heapfinal1318   nsCSSValuePair_heap(const nsCSSValue& aXValue, const nsCSSValue& aYValue)
1319       : nsCSSValuePair(aXValue, aYValue) {}
1320 
1321   NS_INLINE_DECL_REFCOUNTING(nsCSSValuePair_heap)
1322 
1323   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1324 
1325  private:
1326   // Private destructor, to discourage deletion outside of Release():
~nsCSSValuePair_heapfinal1327   ~nsCSSValuePair_heap() {}
1328 };
1329 
1330 struct nsCSSValueTriplet {
nsCSSValueTripletnsCSSValueTriplet1331   nsCSSValueTriplet() { MOZ_COUNT_CTOR(nsCSSValueTriplet); }
nsCSSValueTripletnsCSSValueTriplet1332   explicit nsCSSValueTriplet(nsCSSUnit aUnit)
1333       : mXValue(aUnit), mYValue(aUnit), mZValue(aUnit) {
1334     MOZ_COUNT_CTOR(nsCSSValueTriplet);
1335   }
nsCSSValueTripletnsCSSValueTriplet1336   nsCSSValueTriplet(const nsCSSValue& aXValue, const nsCSSValue& aYValue,
1337                     const nsCSSValue& aZValue)
1338       : mXValue(aXValue), mYValue(aYValue), mZValue(aZValue) {
1339     MOZ_COUNT_CTOR(nsCSSValueTriplet);
1340   }
nsCSSValueTripletnsCSSValueTriplet1341   nsCSSValueTriplet(const nsCSSValueTriplet& aCopy)
1342       : mXValue(aCopy.mXValue), mYValue(aCopy.mYValue), mZValue(aCopy.mZValue) {
1343     MOZ_COUNT_CTOR(nsCSSValueTriplet);
1344   }
~nsCSSValueTripletnsCSSValueTriplet1345   ~nsCSSValueTriplet() { MOZ_COUNT_DTOR(nsCSSValueTriplet); }
1346 
1347   bool operator==(const nsCSSValueTriplet& aOther) const {
1348     return mXValue == aOther.mXValue && mYValue == aOther.mYValue &&
1349            mZValue == aOther.mZValue;
1350   }
1351 
1352   bool operator!=(const nsCSSValueTriplet& aOther) const {
1353     return mXValue != aOther.mXValue || mYValue != aOther.mYValue ||
1354            mZValue != aOther.mZValue;
1355   }
1356 
AllValuesEqualTonsCSSValueTriplet1357   bool AllValuesEqualTo(const nsCSSValue& aValue) const {
1358     return mXValue == aValue && mYValue == aValue && mZValue == aValue;
1359   }
1360 
SetAllValuesTonsCSSValueTriplet1361   void SetAllValuesTo(const nsCSSValue& aValue) {
1362     mXValue = aValue;
1363     mYValue = aValue;
1364     mZValue = aValue;
1365   }
1366 
ResetnsCSSValueTriplet1367   void Reset() {
1368     mXValue.Reset();
1369     mYValue.Reset();
1370     mZValue.Reset();
1371   }
1372 
HasValuensCSSValueTriplet1373   bool HasValue() const {
1374     return mXValue.GetUnit() != eCSSUnit_Null ||
1375            mYValue.GetUnit() != eCSSUnit_Null ||
1376            mZValue.GetUnit() != eCSSUnit_Null;
1377   }
1378 
1379   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
1380 
1381   nsCSSValue mXValue;
1382   nsCSSValue mYValue;
1383   nsCSSValue mZValue;
1384 };
1385 
1386 // nsCSSValueTriplet_heap differs from nsCSSValueTriplet only in being
1387 // refcounted.  It should not be necessary to use this class directly;
1388 // it's an implementation detail of nsCSSValue.
1389 struct nsCSSValueTriplet_heap final : public nsCSSValueTriplet {
1390   // forward constructor
nsCSSValueTriplet_heapfinal1391   nsCSSValueTriplet_heap(const nsCSSValue& aXValue, const nsCSSValue& aYValue,
1392                          const nsCSSValue& aZValue)
1393       : nsCSSValueTriplet(aXValue, aYValue, aZValue) {}
1394 
1395   NS_INLINE_DECL_REFCOUNTING(nsCSSValueTriplet_heap)
1396 
1397   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1398 
1399  private:
1400   // Private destructor, to discourage deletion outside of Release():
~nsCSSValueTriplet_heapfinal1401   ~nsCSSValueTriplet_heap() {}
1402 };
1403 
1404 // This has to be here so that the relationship between nsCSSValuePair
1405 // and nsCSSValuePair_heap is visible.
GetPairValue()1406 inline nsCSSValuePair& nsCSSValue::GetPairValue() {
1407   MOZ_ASSERT(mUnit == eCSSUnit_Pair, "not a pair value");
1408   return *mValue.mPair;
1409 }
1410 
GetPairValue()1411 inline const nsCSSValuePair& nsCSSValue::GetPairValue() const {
1412   MOZ_ASSERT(mUnit == eCSSUnit_Pair, "not a pair value");
1413   return *mValue.mPair;
1414 }
1415 
GetTripletValue()1416 inline nsCSSValueTriplet& nsCSSValue::GetTripletValue() {
1417   MOZ_ASSERT(mUnit == eCSSUnit_Triplet, "not a triplet value");
1418   return *mValue.mTriplet;
1419 }
1420 
GetTripletValue()1421 inline const nsCSSValueTriplet& nsCSSValue::GetTripletValue() const {
1422   MOZ_ASSERT(mUnit == eCSSUnit_Triplet, "not a triplet value");
1423   return *mValue.mTriplet;
1424 }
1425 
1426 // Maybe should be replaced with nsCSSValueList and nsCSSValue::Array?
1427 struct nsCSSValuePairList {
nsCSSValuePairListnsCSSValuePairList1428   nsCSSValuePairList() : mNext(nullptr) { MOZ_COUNT_CTOR(nsCSSValuePairList); }
1429   ~nsCSSValuePairList();
1430 
1431   nsCSSValuePairList* Clone() const;  // makes a deep copy. Infallible.
1432   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
1433 
1434   static bool Equal(const nsCSSValuePairList* aList1,
1435                     const nsCSSValuePairList* aList2);
1436 
1437   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1438 
1439   nsCSSValue mXValue;
1440   nsCSSValue mYValue;
1441   nsCSSValuePairList* mNext;
1442 
1443  private:
nsCSSValuePairListnsCSSValuePairList1444   nsCSSValuePairList(const nsCSSValuePairList& aCopy)  // makes a shallow copy
1445       : mXValue(aCopy.mXValue), mYValue(aCopy.mYValue), mNext(nullptr) {
1446     MOZ_COUNT_CTOR(nsCSSValuePairList);
1447   }
1448 
1449   // We don't want operator== or operator!= because they wouldn't be
1450   // null-safe, which is generally what we need.  Use |Equal| method
1451   // above instead.
1452   bool operator==(const nsCSSValuePairList& aOther) const = delete;
1453   bool operator!=(const nsCSSValuePairList& aOther) const = delete;
1454 };
1455 
1456 // nsCSSValuePairList_heap differs from nsCSSValuePairList only in being
1457 // refcounted.  It should not be necessary to use this class directly;
1458 // it's an implementation detail of nsCSSValue.
1459 struct nsCSSValuePairList_heap final : public nsCSSValuePairList {
1460   NS_INLINE_DECL_REFCOUNTING(nsCSSValuePairList_heap)
1461 
1462   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1463 
1464  private:
1465   // Private destructor, to discourage deletion outside of Release():
~nsCSSValuePairList_heapfinal1466   ~nsCSSValuePairList_heap() {}
1467 };
1468 
1469 // This has to be here so that the relationship between nsCSSValuePairList
1470 // and nsCSSValuePairList_heap is visible.
GetPairListValue()1471 inline nsCSSValuePairList* nsCSSValue::GetPairListValue() {
1472   if (mUnit == eCSSUnit_PairList)
1473     return mValue.mPairList;
1474   else {
1475     MOZ_ASSERT(mUnit == eCSSUnit_PairListDep, "not a pairlist value");
1476     return mValue.mPairListDependent;
1477   }
1478 }
1479 
GetPairListValue()1480 inline const nsCSSValuePairList* nsCSSValue::GetPairListValue() const {
1481   if (mUnit == eCSSUnit_PairList)
1482     return mValue.mPairList;
1483   else {
1484     MOZ_ASSERT(mUnit == eCSSUnit_PairListDep, "not a pairlist value");
1485     return mValue.mPairListDependent;
1486   }
1487 }
1488 
1489 struct nsCSSValueGradientStop {
1490  public:
1491   nsCSSValueGradientStop();
1492   // needed to keep bloat logs happy when we use the TArray
1493   // in nsCSSValueGradient
1494   nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther);
1495   ~nsCSSValueGradientStop();
1496 
1497   nsCSSValue mLocation;
1498   nsCSSValue mColor;
1499   // If mIsInterpolationHint is true, there is no color, just
1500   // a location.
1501   bool mIsInterpolationHint;
1502 
1503   bool operator==(const nsCSSValueGradientStop& aOther) const {
1504     return (mLocation == aOther.mLocation &&
1505             mIsInterpolationHint == aOther.mIsInterpolationHint &&
1506             (mIsInterpolationHint || mColor == aOther.mColor));
1507   }
1508 
1509   bool operator!=(const nsCSSValueGradientStop& aOther) const {
1510     return !(*this == aOther);
1511   }
1512 
1513   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1514 };
1515 
1516 struct nsCSSValueGradient final {
1517   nsCSSValueGradient(bool aIsRadial, bool aIsRepeating);
1518 
1519   // true if gradient is radial, false if it is linear
1520   bool mIsRadial;
1521   bool mIsRepeating;
1522   bool mIsLegacySyntax;  // If true, serialization should use a vendor prefix.
1523   // XXXdholbert This will hopefully be going away soon, if bug 1337655 sticks:
1524   bool mIsMozLegacySyntax;  // (Only makes sense when mIsLegacySyntax is true.)
1525                             // If true, serialization should use -moz prefix.
1526                             // Else, serialization should use -webkit prefix.
1527   bool mIsExplicitSize;
1528   // line position and angle
1529   nsCSSValuePair mBgPos;
1530   nsCSSValue mAngle;
1531 
1532   // Only meaningful if mIsRadial is true
1533  private:
1534   nsCSSValue mRadialValues[2];
1535 
1536  public:
GetRadialShapefinal1537   nsCSSValue& GetRadialShape() {
1538     MOZ_ASSERT(!mIsExplicitSize);
1539     return mRadialValues[0];
1540   }
GetRadialShapefinal1541   const nsCSSValue& GetRadialShape() const {
1542     MOZ_ASSERT(!mIsExplicitSize);
1543     return mRadialValues[0];
1544   }
GetRadialSizefinal1545   nsCSSValue& GetRadialSize() {
1546     MOZ_ASSERT(!mIsExplicitSize);
1547     return mRadialValues[1];
1548   }
GetRadialSizefinal1549   const nsCSSValue& GetRadialSize() const {
1550     MOZ_ASSERT(!mIsExplicitSize);
1551     return mRadialValues[1];
1552   }
GetRadiusXfinal1553   nsCSSValue& GetRadiusX() {
1554     MOZ_ASSERT(mIsExplicitSize);
1555     return mRadialValues[0];
1556   }
GetRadiusXfinal1557   const nsCSSValue& GetRadiusX() const {
1558     MOZ_ASSERT(mIsExplicitSize);
1559     return mRadialValues[0];
1560   }
GetRadiusYfinal1561   nsCSSValue& GetRadiusY() {
1562     MOZ_ASSERT(mIsExplicitSize);
1563     return mRadialValues[1];
1564   }
GetRadiusYfinal1565   const nsCSSValue& GetRadiusY() const {
1566     MOZ_ASSERT(mIsExplicitSize);
1567     return mRadialValues[1];
1568   }
1569 
1570   InfallibleTArray<nsCSSValueGradientStop> mStops;
1571 
1572   bool operator==(const nsCSSValueGradient& aOther) const {
1573     if (mIsRadial != aOther.mIsRadial || mIsRepeating != aOther.mIsRepeating ||
1574         mIsLegacySyntax != aOther.mIsLegacySyntax ||
1575         mIsMozLegacySyntax != aOther.mIsMozLegacySyntax ||
1576         mIsExplicitSize != aOther.mIsExplicitSize || mBgPos != aOther.mBgPos ||
1577         mAngle != aOther.mAngle ||
1578         mRadialValues[0] != aOther.mRadialValues[0] ||
1579         mRadialValues[1] != aOther.mRadialValues[1])
1580       return false;
1581 
1582     if (mStops.Length() != aOther.mStops.Length()) return false;
1583 
1584     for (uint32_t i = 0; i < mStops.Length(); i++) {
1585       if (mStops[i] != aOther.mStops[i]) return false;
1586     }
1587 
1588     return true;
1589   }
1590 
1591   bool operator!=(const nsCSSValueGradient& aOther) const {
1592     return !(*this == aOther);
1593   }
1594 
1595   NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient)
1596 
1597   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1598 
1599  private:
1600   // Private destructor, to discourage deletion outside of Release():
~nsCSSValueGradientfinal1601   ~nsCSSValueGradient() {}
1602 
1603   nsCSSValueGradient(const nsCSSValueGradient& aOther) = delete;
1604   nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther) = delete;
1605 };
1606 
1607 // A string value used primarily to represent variable references.
1608 //
1609 // Animation code, specifically the KeyframeUtils class, also uses this
1610 // type as a container for various string values including:
1611 //
1612 // * Shorthand property values
1613 // * Shorthand sentinel values used for testing failure conditions
1614 // * Invalid longhand property values
1615 //
1616 // For the most part, the above values are not passed to functions that
1617 // manipulate nsCSSValue objects in a generic fashion. Instead KeyframeUtils
1618 // extracts the string from the nsCSSValueTokenStream and passes that around
1619 // instead. The single exception is nsCSSValue::AppendToString which we use
1620 // to serialize the string contained in the nsCSSValueTokenStream by ensuring
1621 // the mShorthandPropertyID is set to eCSSProperty_UNKNOWN.
1622 struct nsCSSValueTokenStream final {
1623   nsCSSValueTokenStream();
1624 
1625  private:
1626   // Private destructor, to discourage deletion outside of Release():
1627   ~nsCSSValueTokenStream();
1628 
1629  public:
1630   bool operator==(const nsCSSValueTokenStream& aOther) const {
1631     // This is not safe to call OMT, due to the URI/Principal Equals calls.
1632     MOZ_ASSERT(NS_IsMainThread());
1633 
1634     bool eq;
1635     return mPropertyID == aOther.mPropertyID &&
1636            mShorthandPropertyID == aOther.mShorthandPropertyID &&
1637            mTokenStream.Equals(aOther.mTokenStream) &&
1638            mLevel == aOther.mLevel &&
1639            (mBaseURI == aOther.mBaseURI ||
1640             (mBaseURI && aOther.mBaseURI &&
1641              NS_SUCCEEDED(mBaseURI->Equals(aOther.mBaseURI, &eq)) && eq)) &&
1642            (mSheetURI == aOther.mSheetURI ||
1643             (mSheetURI && aOther.mSheetURI &&
1644              NS_SUCCEEDED(mSheetURI->Equals(aOther.mSheetURI, &eq)) && eq)) &&
1645            (mSheetPrincipal == aOther.mSheetPrincipal ||
1646             (mSheetPrincipal && aOther.mSheetPrincipal &&
1647              NS_SUCCEEDED(
1648                  mSheetPrincipal->Equals(aOther.mSheetPrincipal, &eq)) &&
1649              eq));
1650   }
1651 
1652   bool operator!=(const nsCSSValueTokenStream& aOther) const {
1653     return !(*this == aOther);
1654   }
1655 
1656   NS_INLINE_DECL_REFCOUNTING(nsCSSValueTokenStream)
1657 
1658   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1659 
1660   // The property that has mTokenStream as its unparsed specified value.
1661   // When a variable reference is used in a shorthand property, a
1662   // TokenStream value is stored as the specified value for each of its
1663   // component longhand properties.
1664   nsCSSPropertyID mPropertyID;
1665 
1666   // The shorthand property that had a value with a variable reference,
1667   // which caused the longhand property identified by mPropertyID to have
1668   // a TokenStream value.
1669   nsCSSPropertyID mShorthandPropertyID;
1670 
1671   // The unparsed CSS corresponding to the specified value of the property.
1672   // When the value of a shorthand property has a variable reference, the
1673   // same mTokenStream value is used on each of the nsCSSValueTokenStream
1674   // objects that will be set by parsing the shorthand.
1675   nsString mTokenStream;
1676 
1677   nsCOMPtr<nsIURI> mBaseURI;
1678   nsCOMPtr<nsIURI> mSheetURI;
1679   nsCOMPtr<nsIPrincipal> mSheetPrincipal;
1680   // XXX Should store sheet here (see Bug 952338)
1681   // mozilla::CSSStyleSheet* mSheet;
1682   uint32_t mLineNumber;
1683   uint32_t mLineOffset;
1684   mozilla::SheetType mLevel;
1685 
1686  private:
1687   nsCSSValueTokenStream(const nsCSSValueTokenStream& aOther) = delete;
1688   nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) =
1689       delete;
1690 };
1691 
1692 class nsCSSValueFloatColor final {
1693  public:
nsCSSValueFloatColor(float aComponent1,float aComponent2,float aComponent3,float aAlpha)1694   nsCSSValueFloatColor(float aComponent1, float aComponent2, float aComponent3,
1695                        float aAlpha)
1696       : mComponent1(aComponent1),
1697         mComponent2(aComponent2),
1698         mComponent3(aComponent3),
1699         mAlpha(aAlpha) {
1700     // We may copy nsCSSValueFloatColor and do some comparisons on them.
1701     // In order to get the correct result, we have to make sure each component
1702     // is finite.
1703     MOZ_ASSERT(mozilla::IsFinite(aComponent1) &&
1704                    mozilla::IsFinite(aComponent2) &&
1705                    mozilla::IsFinite(aComponent3) && mozilla::IsFinite(aAlpha),
1706                "Caller must ensure color components are finite");
1707   }
1708 
1709  private:
1710   // Private destructor, to discourage deletion outside of Release():
~nsCSSValueFloatColor()1711   ~nsCSSValueFloatColor() {}
1712 
1713  public:
1714   bool operator==(nsCSSValueFloatColor& aOther) const;
1715 
1716   nscolor GetColorValue(nsCSSUnit aUnit) const;
Comp1()1717   float Comp1() const { return mComponent1; }
Comp2()1718   float Comp2() const { return mComponent2; }
Comp3()1719   float Comp3() const { return mComponent3; }
Alpha()1720   float Alpha() const { return mAlpha; }
1721   bool IsNonTransparentColor() const;
1722 
1723   void AppendToString(nsCSSUnit aUnit, nsAString& aResult) const;
1724 
1725   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
1726 
1727   NS_INLINE_DECL_REFCOUNTING(nsCSSValueFloatColor)
1728 
1729  private:
1730   // The range of each component is.
1731   // [0, 1] for HSLColor and HSLAColor. mComponent1 for hue, mComponent2 for
1732   //                                    saturation, mComponent3 for lightness.
1733   //                                    [0, 1] for saturation and lightness
1734   //                                    represents [0%, 100%].
1735   //                                    [0, 1] for hue represents
1736   //                                    [0deg, 360deg].
1737   //
1738   // [-float::max(), float::max()] for PercentageRGBColor, PercentageRGBAColor.
1739   //                               1.0 means 100%.
1740   float mComponent1;
1741   float mComponent2;
1742   float mComponent3;
1743   float mAlpha;
1744 
1745   nsCSSValueFloatColor(const nsCSSValueFloatColor& aOther) = delete;
1746   nsCSSValueFloatColor& operator=(const nsCSSValueFloatColor& aOther) = delete;
1747 };
1748 
1749 struct nsCSSCornerSizes {
1750   nsCSSCornerSizes(void);
1751   nsCSSCornerSizes(const nsCSSCornerSizes& aCopy);
1752   ~nsCSSCornerSizes();
1753 
1754   // argument is a "full corner" constant from nsStyleConsts.h
GetCornernsCSSCornerSizes1755   nsCSSValue const& GetCorner(uint32_t aCorner) const {
1756     return this->*corners[aCorner];
1757   }
GetCornernsCSSCornerSizes1758   nsCSSValue& GetCorner(uint32_t aCorner) { return this->*corners[aCorner]; }
1759 
1760   bool operator==(const nsCSSCornerSizes& aOther) const {
NS_FOR_CSS_FULL_CORNERSnsCSSCornerSizes1761     NS_FOR_CSS_FULL_CORNERS(corner) {
1762       if (this->GetCorner(corner) != aOther.GetCorner(corner)) return false;
1763     }
1764     return true;
1765   }
1766 
1767   bool operator!=(const nsCSSCornerSizes& aOther) const {
NS_FOR_CSS_FULL_CORNERSnsCSSCornerSizes1768     NS_FOR_CSS_FULL_CORNERS(corner) {
1769       if (this->GetCorner(corner) != aOther.GetCorner(corner)) return true;
1770     }
1771     return false;
1772   }
1773 
HasValuensCSSCornerSizes1774   bool HasValue() const {
1775     NS_FOR_CSS_FULL_CORNERS(corner) {
1776       if (this->GetCorner(corner).GetUnit() != eCSSUnit_Null) return true;
1777     }
1778     return false;
1779   }
1780 
1781   void Reset();
1782 
1783   nsCSSValue mTopLeft;
1784   nsCSSValue mTopRight;
1785   nsCSSValue mBottomRight;
1786   nsCSSValue mBottomLeft;
1787 
1788  protected:
1789   typedef nsCSSValue nsCSSCornerSizes::*corner_type;
1790   static const corner_type corners[4];
1791 };
1792 
1793 #endif /* nsCSSValue_h___ */
1794