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 /*
8  * structs that contain the data provided by nsStyleContext, the
9  * internal API for computed style data for an element
10  */
11 
12 #ifndef nsStyleStruct_h___
13 #define nsStyleStruct_h___
14 
15 #include "mozilla/ArenaObjectID.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/CSSVariableValues.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/SheetType.h"
20 #include "mozilla/StaticPtr.h"
21 #include "mozilla/StyleComplexColor.h"
22 #include "mozilla/StyleStructContext.h"
23 #include "mozilla/UniquePtr.h"
24 #include "nsColor.h"
25 #include "nsCoord.h"
26 #include "nsMargin.h"
27 #include "nsFont.h"
28 #include "nsStyleCoord.h"
29 #include "nsStyleConsts.h"
30 #include "nsChangeHint.h"
31 #include "nsPresContext.h"
32 #include "nsCOMPtr.h"
33 #include "nsCOMArray.h"
34 #include "nsTArray.h"
35 #include "nsCSSValue.h"
36 #include "imgRequestProxy.h"
37 #include "Orientation.h"
38 #include "CounterStyleManager.h"
39 #include <cstddef> // offsetof()
40 #include <utility>
41 #include "X11UndefineNone.h"
42 
43 class nsIFrame;
44 class nsIURI;
45 class nsStyleContext;
46 class nsTextFrame;
47 class imgIContainer;
48 struct nsStyleVisibility;
49 namespace mozilla {
50 namespace dom {
51 class ImageTracker;
52 } // namespace dom
53 } // namespace mozilla
54 
55 // Includes nsStyleStructID.
56 #include "nsStyleStructFwd.h"
57 
58 // Bits for each struct.
59 // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
60 #define NS_STYLE_INHERIT_MASK              0x000ffffff
61 
62 // Bits for inherited structs.
63 #define NS_STYLE_INHERITED_STRUCT_MASK \
64   ((nsStyleStructID_size_t(1) << nsStyleStructID_Inherited_Count) - 1)
65 // Bits for reset structs.
66 #define NS_STYLE_RESET_STRUCT_MASK \
67   (((nsStyleStructID_size_t(1) << nsStyleStructID_Reset_Count) - 1) \
68    << nsStyleStructID_Inherited_Count)
69 
70 // Additional bits for nsStyleContext's mBits:
71 // See nsStyleContext::HasTextDecorationLines
72 #define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000
73 // See nsStyleContext::HasPseudoElementData.
74 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA   0x002000000
75 // See nsStyleContext::RelevantLinkIsVisited
76 #define NS_STYLE_RELEVANT_LINK_VISITED     0x004000000
77 // See nsStyleContext::IsStyleIfVisited
78 #define NS_STYLE_IS_STYLE_IF_VISITED       0x008000000
79 // See nsStyleContext::HasChildThatUsesGrandancestorStyle
80 #define NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE 0x010000000
81 // See nsStyleContext::IsShared
82 #define NS_STYLE_IS_SHARED                 0x020000000
83 // See nsStyleContext::AssertStructsNotUsedElsewhere
84 // (This bit is currently only used in #ifdef DEBUG code.)
85 #define NS_STYLE_IS_GOING_AWAY             0x040000000
86 // See nsStyleContext::ShouldSuppressLineBreak
87 #define NS_STYLE_SUPPRESS_LINEBREAK        0x080000000
88 // See nsStyleContext::IsInDisplayNoneSubtree
89 #define NS_STYLE_IN_DISPLAY_NONE_SUBTREE   0x100000000
90 // See nsStyleContext::FindChildWithRules
91 #define NS_STYLE_INELIGIBLE_FOR_SHARING    0x200000000
92 // See nsStyleContext::HasChildThatUsesResetStyle
93 #define NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE 0x400000000
94 // See nsStyleContext::IsTextCombined
95 #define NS_STYLE_IS_TEXT_COMBINED          0x800000000
96 // See nsStyleContext::GetPseudoEnum
97 #define NS_STYLE_CONTEXT_TYPE_SHIFT        36
98 
99 // Additional bits for nsRuleNode's mDependentBits:
100 #define NS_RULE_NODE_IS_ANIMATION_RULE      0x01000000
101 // Free bit                                 0x02000000
102 #define NS_RULE_NODE_USED_DIRECTLY          0x04000000
103 #define NS_RULE_NODE_IS_IMPORTANT           0x08000000
104 #define NS_RULE_NODE_LEVEL_MASK             0xf0000000
105 #define NS_RULE_NODE_LEVEL_SHIFT            28
106 
107 // Additional bits for nsRuleNode's mNoneBits:
108 #define NS_RULE_NODE_HAS_ANIMATION_DATA     0x80000000
109 
110 static_assert(int(mozilla::SheetType::Count) - 1 <=
111                 (NS_RULE_NODE_LEVEL_MASK >> NS_RULE_NODE_LEVEL_SHIFT),
112               "NS_RULE_NODE_LEVEL_MASK cannot fit SheetType");
113 
114 static_assert(NS_STYLE_INHERIT_MASK == (1 << nsStyleStructID_Length) - 1,
115               "NS_STYLE_INHERIT_MASK is not correct");
116 
117 static_assert((NS_RULE_NODE_IS_ANIMATION_RULE & NS_STYLE_INHERIT_MASK) == 0,
118   "NS_RULE_NODE_IS_ANIMATION_RULE must not overlap the style struct bits.");
119 
120 namespace mozilla {
121 
122 struct Position {
123   using Coord = nsStyleCoord::CalcValue;
124 
125   Coord mXPosition, mYPosition;
126 
127   // Initialize nothing
PositionPosition128   Position() {}
129 
130   // Sets both mXPosition and mYPosition to the given percent value for the
131   // initial property-value (e.g. 0.0f for "0% 0%", or 0.5f for "50% 50%")
132   void SetInitialPercentValues(float aPercentVal);
133 
134   // Sets both mXPosition and mYPosition to 0 (app units) for the
135   // initial property-value as a length with no percentage component.
136   void SetInitialZeroValues();
137 
138   // True if the effective background image position described by this depends
139   // on the size of the corresponding frame.
DependsOnPositioningAreaSizePosition140   bool DependsOnPositioningAreaSize() const {
141     return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
142   }
143 
144   bool operator==(const Position& aOther) const {
145     return mXPosition == aOther.mXPosition &&
146       mYPosition == aOther.mYPosition;
147   }
148   bool operator!=(const Position& aOther) const {
149     return !(*this == aOther);
150   }
151 };
152 
153 } // namespace mozilla
154 
155 // The lifetime of these objects is managed by the presshell's arena.
156 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont
157 {
158   nsStyleFont(const nsFont& aFont, StyleStructContext aContext);
159   nsStyleFont(const nsStyleFont& aStyleFont);
160   explicit nsStyleFont(StyleStructContext aContext);
~nsStyleFontnsStyleFont161   ~nsStyleFont() {
162     MOZ_COUNT_DTOR(nsStyleFont);
163   }
FinishStylensStyleFont164   void FinishStyle(nsPresContext* aPresContext) {}
165 
166   nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
MaxDifferencensStyleFont167   static nsChangeHint MaxDifference() {
168     return NS_STYLE_HINT_REFLOW |
169            nsChangeHint_NeutralChange;
170   }
DifferenceAlwaysHandledForDescendantsnsStyleFont171   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
172     // CalcDifference never returns the reflow hints that are sometimes
173     // handled for descendants as hints not handled for descendants.
174     return nsChangeHint_NeedReflow |
175            nsChangeHint_ReflowChangesSizeOrPosition |
176            nsChangeHint_ClearAncestorIntrinsics;
177   }
178 
179   /**
180    * Return aSize multiplied by the current text zoom factor (in aPresContext).
181    * aSize is allowed to be negative, but the caller is expected to deal with
182    * negative results.  The result is clamped to nscoord_MIN .. nscoord_MAX.
183    */
184   static nscoord ZoomText(StyleStructContext aContext, nscoord aSize);
185   /**
186    * Return aSize divided by the current text zoom factor (in aPresContext).
187    * aSize is allowed to be negative, but the caller is expected to deal with
188    * negative results.  The result is clamped to nscoord_MIN .. nscoord_MAX.
189    */
190   static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
191   static already_AddRefed<nsIAtom> GetLanguage(StyleStructContext aPresContext);
192 
newnsStyleFont193   void* operator new(size_t sz, nsStyleFont* aSelf) { return aSelf; }
newnsStyleFont194   void* operator new(size_t sz, nsPresContext* aContext) {
195     return aContext->PresShell()->
196       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleFont, sz);
197   }
198   void Destroy(nsPresContext* aContext);
199 
200   void EnableZoom(nsPresContext* aContext, bool aEnable);
201 
202   nsFont  mFont;        // [inherited]
203   nscoord mSize;        // [inherited] Our "computed size". Can be different
204                         // from mFont.size which is our "actual size" and is
205                         // enforced to be >= the user's preferred min-size.
206                         // mFont.size should be used for display purposes
207                         // while mSize is the value to return in
208                         // getComputedStyle() for example.
209   uint8_t mGenericID;   // [inherited] generic CSS font family, if any;
210                         // value is a kGenericFont_* constant, see nsFont.h.
211 
212   // MathML scriptlevel support
213   int8_t  mScriptLevel;          // [inherited]
214   // MathML  mathvariant support
215   uint8_t mMathVariant;          // [inherited]
216   // MathML displaystyle support
217   uint8_t mMathDisplay;         // [inherited]
218 
219   // allow different min font-size for certain cases
220   uint8_t mMinFontSizeRatio;     // [inherited] percent * 100
221 
222   // was mLanguage set based on a lang attribute in the document?
223   bool mExplicitLanguage;        // [inherited]
224 
225   // should calls to ZoomText() and UnZoomText() be made to the font
226   // size on this nsStyleFont?
227   bool mAllowZoom;               // [inherited]
228 
229   // The value mSize would have had if scriptminsize had never been applied
230   nscoord mScriptUnconstrainedSize;
231   nscoord mScriptMinSize;        // [inherited] length
232   float   mScriptSizeMultiplier; // [inherited]
233   nsCOMPtr<nsIAtom> mLanguage;   // [inherited]
234 };
235 
236 struct nsStyleGradientStop
237 {
238   nsStyleCoord mLocation; // percent, coord, calc, none
239   nscolor mColor;
240   bool mIsInterpolationHint;
241 
242   // Use ==/!= on nsStyleGradient instead of on the gradient stop.
243   bool operator==(const nsStyleGradientStop&) const = delete;
244   bool operator!=(const nsStyleGradientStop&) const = delete;
245 };
246 
247 class nsStyleGradient final
248 {
249 public:
250   nsStyleGradient();
251   uint8_t mShape;  // NS_STYLE_GRADIENT_SHAPE_*
252   uint8_t mSize;   // NS_STYLE_GRADIENT_SIZE_*;
253                    // not used (must be FARTHEST_CORNER) for linear shape
254   bool mRepeating;
255   bool mLegacySyntax;
256 
257   nsStyleCoord mBgPosX; // percent, coord, calc, none
258   nsStyleCoord mBgPosY; // percent, coord, calc, none
259   nsStyleCoord mAngle;  // none, angle
260 
261   nsStyleCoord mRadiusX; // percent, coord, calc, none
262   nsStyleCoord mRadiusY; // percent, coord, calc, none
263 
264   // stops are in the order specified in the stylesheet
265   nsTArray<nsStyleGradientStop> mStops;
266 
267   bool operator==(const nsStyleGradient& aOther) const;
268   bool operator!=(const nsStyleGradient& aOther) const {
269     return !(*this == aOther);
270   }
271 
272   bool IsOpaque();
273   bool HasCalc();
274   uint32_t Hash(PLDHashNumber aHash);
275 
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleGradient)276   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleGradient)
277 
278 private:
279   // Private destructor, to discourage deletion outside of Release():
280   ~nsStyleGradient() {}
281 
282   nsStyleGradient(const nsStyleGradient& aOther) = delete;
283   nsStyleGradient& operator=(const nsStyleGradient& aOther) = delete;
284 };
285 
286 /**
287  * A wrapper for an imgRequestProxy that supports off-main-thread creation
288  * and equality comparison.
289  *
290  * An nsStyleImageRequest can be created in two ways:
291  *
292  * 1. Using the constructor that takes an imgRequestProxy.  This must
293  *    be called from the main thread.  The nsStyleImageRequest is
294  *    immediately considered "resolved", and the get() method that
295  *    returns the imgRequestProxy can be called.
296  *
297  * 2. Using the constructor that takes the URL, base URI, referrer
298  *    and principal that can be used to inititiate an image load and
299  *    produce an imgRequestProxy later.  This can be called from
300  *    any thread.  The nsStyleImageRequest is not considered "resolved"
301  *    at this point, and the Resolve() method must be called later
302  *    to initiate the image load and make calls to get() valid.
303  *
304  * Calls to TrackImage(), UntrackImage(), LockImage(), UnlockImage() and
305  * RequestDiscard() are made to the imgRequestProxy and ImageTracker as
306  * appropriate, according to the mode flags passed in to the constructor.
307  *
308  * The main thread constructor takes a pointer to the css::ImageValue that
309  * is the specified url() value, while the off-main-thread constructor
310  * creates a new css::ImageValue to represent the url() information passed
311  * to the constructor.  This ImageValue is held on to for the comparisons done
312  * in DefinitelyEquals(), so that we don't need to call into the non-OMT-safe
313  * Equals() on the nsIURI objects returned from imgRequestProxy::GetURI().
314  */
315 class nsStyleImageRequest
316 {
317 public:
318   // Flags describing whether the imgRequestProxy must be tracked in the
319   // ImageTracker, whether LockImage/UnlockImage calls will be made
320   // when obtaining and releasing the imgRequestProxy, and whether
321   // RequestDiscard will be called on release.
322   enum class Mode : uint8_t {
323     // The imgRequestProxy will be added to the ImageTracker when resolved
324     // Without this flag, the nsStyleImageRequest itself will call LockImage/
325     // UnlockImage on the imgRequestProxy, rather than leaving locking to the
326     // ImageTracker to manage.
327     //
328     // This flag is currently used by all nsStyleImageRequests except
329     // those for list-style-image and cursor.
330     Track = 0x1,
331 
332     // The imgRequestProxy will have its RequestDiscard method called when
333     // the nsStyleImageRequest is going away.
334     //
335     // This is currently used only for cursor images.
336     Discard = 0x2,
337   };
338 
339   // Must be called from the main thread.
340   //
341   // aImageTracker must be non-null iff aModeFlags contains Track.
342   nsStyleImageRequest(Mode aModeFlags,
343                       imgRequestProxy* aRequestProxy,
344                       mozilla::css::ImageValue* aImageValue,
345                       mozilla::dom::ImageTracker* aImageTracker);
346 
347   // Can be called from any thread, but Resolve() must be called later
348   // on the main thread before get() can be used.
349   nsStyleImageRequest(
350       Mode aModeFlags,
351       nsStringBuffer* aURLBuffer,
352       already_AddRefed<mozilla::PtrHolder<nsIURI>> aBaseURI,
353       already_AddRefed<mozilla::PtrHolder<nsIURI>> aReferrer,
354       already_AddRefed<mozilla::PtrHolder<nsIPrincipal>> aPrincipal);
355 
356   bool Resolve(nsPresContext* aPresContext);
IsResolved()357   bool IsResolved() const { return mResolved; }
358 
get()359   imgRequestProxy* get() {
360     MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
361     MOZ_ASSERT(NS_IsMainThread());
362     return mRequestProxy.get();
363   }
get()364   const imgRequestProxy* get() const {
365     return const_cast<nsStyleImageRequest*>(this)->get();
366   }
367 
368   // Returns whether the ImageValue objects in the two nsStyleImageRequests
369   // return true from URLValueData::DefinitelyEqualURIs.
370   bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
371 
372   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleImageRequest);
373 
374 private:
375   ~nsStyleImageRequest();
376   nsStyleImageRequest& operator=(const nsStyleImageRequest& aOther) = delete;
377 
378   void MaybeTrackAndLock();
379 
380   RefPtr<imgRequestProxy> mRequestProxy;
381   RefPtr<mozilla::css::ImageValue> mImageValue;
382   RefPtr<mozilla::dom::ImageTracker> mImageTracker;
383 
384   Mode mModeFlags;
385   bool mResolved;
386 };
387 
388 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsStyleImageRequest::Mode)
389 
390 enum nsStyleImageType {
391   eStyleImageType_Null,
392   eStyleImageType_Image,
393   eStyleImageType_Gradient,
394   eStyleImageType_Element
395 };
396 
397 struct CachedBorderImageData
398 {
399   // Caller are expected to ensure that the value of aSVGViewportSize is
400   // different from the cached one since the method won't do the check.
401   void SetCachedSVGViewportSize(const mozilla::Maybe<nsSize>& aSVGViewportSize);
402   const mozilla::Maybe<nsSize>& GetCachedSVGViewportSize();
403   void PurgeCachedImages();
404   void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage);
405   imgIContainer* GetSubImage(uint8_t aIndex);
406 
407 private:
408   // If this is a SVG border-image, we save the size of the SVG viewport that
409   // we used when rasterizing any cached border-image subimages. (The viewport
410   // size matters for percent-valued sizes & positions in inner SVG doc).
411   mozilla::Maybe<nsSize> mCachedSVGViewportSize;
412   nsCOMArray<imgIContainer> mSubImages;
413 };
414 
415 /**
416  * Represents a paintable image of one of the following types.
417  * (1) A real image loaded from an external source.
418  * (2) A CSS linear or radial gradient.
419  * (3) An element within a document, or an <img>, <video>, or <canvas> element
420  *     not in a document.
421  * (*) Optionally a crop rect can be set to paint a partial (rectangular)
422  * region of an image. (Currently, this feature is only supported with an
423  * image of type (1)).
424  */
425 struct nsStyleImage
426 {
427   nsStyleImage();
428   ~nsStyleImage();
429   nsStyleImage(const nsStyleImage& aOther);
430   nsStyleImage& operator=(const nsStyleImage& aOther);
431 
432   void SetNull();
433   void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
434   void SetGradientData(nsStyleGradient* aGradient);
435   void SetElementId(const char16_t* aElementId);
436   void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
437 
ResolveImagensStyleImage438   void ResolveImage(nsPresContext* aContext) {
439     MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
440     if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
441       mImage->Resolve(aContext);
442     }
443   }
444 
GetTypensStyleImage445   nsStyleImageType GetType() const {
446     return mType;
447   }
GetImageRequestnsStyleImage448   nsStyleImageRequest* GetImageRequest() const {
449     MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
450     MOZ_ASSERT(mImage);
451     return mImage;
452   }
GetImageDatansStyleImage453   imgRequestProxy* GetImageData() const {
454     return GetImageRequest()->get();
455   }
GetGradientDatansStyleImage456   nsStyleGradient* GetGradientData() const {
457     NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
458     return mGradient;
459   }
GetElementIdnsStyleImage460   const char16_t* GetElementId() const {
461     NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
462     return mElementId;
463   }
GetCropRectnsStyleImage464   const mozilla::UniquePtr<nsStyleSides>& GetCropRect() const {
465     NS_ASSERTION(mType == eStyleImageType_Image,
466                  "Only image data can have a crop rect");
467     return mCropRect;
468   }
469 
470   /**
471    * Compute the actual crop rect in pixels, using the source image bounds.
472    * The computation involves converting percentage unit to pixel unit and
473    * clamping each side value to fit in the source image bounds.
474    * @param aActualCropRect the computed actual crop rect.
475    * @param aIsEntireImage true iff |aActualCropRect| is identical to the
476    * source image bounds.
477    * @return true iff |aActualCropRect| holds a meaningful value.
478    */
479   bool ComputeActualCropRect(nsIntRect& aActualCropRect,
480                                bool* aIsEntireImage = nullptr) const;
481 
482   /**
483    * Starts the decoding of a image.
484    */
485   nsresult StartDecoding() const;
486   /**
487    * @return true if the item is definitely opaque --- i.e., paints every
488    * pixel within its bounds opaquely, and the bounds contains at least a pixel.
489    */
490   bool IsOpaque() const;
491   /**
492    * @return true if this image is fully loaded, and its size is calculated;
493    * always returns true if |mType| is |eStyleImageType_Gradient| or
494    * |eStyleImageType_Element|.
495    */
496   bool IsComplete() const;
497   /**
498    * @return true if this image is loaded without error;
499    * always returns true if |mType| is |eStyleImageType_Gradient| or
500    * |eStyleImageType_Element|.
501    */
502   bool IsLoaded() const;
503   /**
504    * @return true if it is 100% confident that this image contains no pixel
505    * to draw.
506    */
IsEmptynsStyleImage507   bool IsEmpty() const {
508     // There are some other cases when the image will be empty, for example
509     // when the crop rect is empty. However, checking the emptiness of crop
510     // rect is non-trivial since each side value can be specified with
511     // percentage unit, which can not be evaluated until the source image size
512     // is available. Therefore, we currently postpone the evaluation of crop
513     // rect until the actual rendering time --- alternatively until GetOpaqueRegion()
514     // is called.
515     return mType == eStyleImageType_Null;
516   }
517 
518   bool operator==(const nsStyleImage& aOther) const;
519   bool operator!=(const nsStyleImage& aOther) const {
520     return !(*this == aOther);
521   }
522 
ImageDataEqualsnsStyleImage523   bool ImageDataEquals(const nsStyleImage& aOther) const
524   {
525     return GetType() == eStyleImageType_Image &&
526            aOther.GetType() == eStyleImageType_Image &&
527            GetImageData() == aOther.GetImageData();
528   }
529 
530   // These methods are used for the caller to caches the sub images created
531   // during a border-image paint operation
532   inline void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const;
533   inline imgIContainer* GetSubImage(uint8_t aIndex) const;
534   void PurgeCacheForViewportChange(
535     const mozilla::Maybe<nsSize>& aSVGViewportSize,
536     const bool aHasIntrinsicRatio) const;
537 
538 private:
539   void DoCopy(const nsStyleImage& aOther);
540   void EnsureCachedBIData() const;
541 
542   // This variable keeps some cache data for border image and is lazily
543   // allocated since it is only used in border image case.
544   mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
545 
546   nsStyleImageType mType;
547   union {
548     nsStyleImageRequest* mImage;
549     nsStyleGradient* mGradient;
550     char16_t* mElementId;
551   };
552 
553   // This is _currently_ used only in conjunction with eStyleImageType_Image.
554   mozilla::UniquePtr<nsStyleSides> mCropRect;
555 };
556 
557 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
558 {
559   explicit nsStyleColor(StyleStructContext aContext);
560   nsStyleColor(const nsStyleColor& aOther);
~nsStyleColornsStyleColor561   ~nsStyleColor() {
562     MOZ_COUNT_DTOR(nsStyleColor);
563   }
FinishStylensStyleColor564   void FinishStyle(nsPresContext* aPresContext) {}
565 
CalcComplexColornsStyleColor566   nscolor CalcComplexColor(const mozilla::StyleComplexColor& aColor) const {
567     return mozilla::LinearBlendColors(aColor.mColor, mColor,
568                                       aColor.mForegroundRatio);
569   }
570 
571   nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
MaxDifferencensStyleColor572   static nsChangeHint MaxDifference() {
573     return nsChangeHint_RepaintFrame;
574   }
DifferenceAlwaysHandledForDescendantsnsStyleColor575   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
576     // CalcDifference never returns the reflow hints that are sometimes
577     // handled for descendants at all.
578     return nsChangeHint(0);
579   }
580 
newnsStyleColor581   void* operator new(size_t sz, nsStyleColor* aSelf) { return aSelf; }
newnsStyleColor582   void* operator new(size_t sz, nsPresContext* aContext) {
583     return aContext->PresShell()->
584       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColor, sz);
585   }
DestroynsStyleColor586   void Destroy(nsPresContext* aContext) {
587     this->~nsStyleColor();
588     aContext->PresShell()->
589       FreeByObjectID(mozilla::eArenaObjectID_nsStyleColor, this);
590   }
591 
592   // Don't add ANY members to this struct!  We can achieve caching in the rule
593   // tree (rather than the style tree) by letting color stay by itself! -dwh
594   nscolor mColor;                 // [inherited]
595 };
596 
597 /**
598  * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
599  * always has length >= 1.
600  */
601 template<typename T>
602 class nsStyleAutoArray
603 {
604 public:
605   // This constructor places a single element in mFirstElement.
606   enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT };
nsStyleAutoArray(WithSingleInitialElement)607   explicit nsStyleAutoArray(WithSingleInitialElement) {}
nsStyleAutoArray(const nsStyleAutoArray & aOther)608   nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; }
609   nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) {
610     mFirstElement = aOther.mFirstElement;
611     mOtherElements = aOther.mOtherElements;
612     return *this;
613   }
614 
615   bool operator==(const nsStyleAutoArray& aOther) const {
616     return Length() == aOther.Length() &&
617            mFirstElement == aOther.mFirstElement &&
618            mOtherElements == aOther.mOtherElements;
619   }
620   bool operator!=(const nsStyleAutoArray& aOther) const {
621     return !(*this == aOther);
622   }
623 
Length()624   size_t Length() const {
625     return mOtherElements.Length() + 1;
626   }
627   const T& operator[](size_t aIndex) const {
628     return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
629   }
630   T& operator[](size_t aIndex) {
631     return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
632   }
633 
EnsureLengthAtLeast(size_t aMinLen)634   void EnsureLengthAtLeast(size_t aMinLen) {
635     if (aMinLen > 0) {
636       mOtherElements.EnsureLengthAtLeast(aMinLen - 1);
637     }
638   }
639 
SetLengthNonZero(size_t aNewLen)640   void SetLengthNonZero(size_t aNewLen) {
641     MOZ_ASSERT(aNewLen > 0);
642     mOtherElements.SetLength(aNewLen - 1);
643   }
644 
TruncateLengthNonZero(size_t aNewLen)645   void TruncateLengthNonZero(size_t aNewLen) {
646     MOZ_ASSERT(aNewLen > 0);
647     MOZ_ASSERT(aNewLen <= Length());
648     mOtherElements.TruncateLength(aNewLen - 1);
649   }
650 
651 private:
652   T mFirstElement;
653   nsTArray<T> mOtherElements;
654 };
655 
656 struct nsStyleImageLayers {
657   // Indices into kBackgroundLayerTable and kMaskLayerTable
658   enum {
659     shorthand = 0,
660     color,
661     image,
662     repeat,
663     positionX,
664     positionY,
665     clip,
666     origin,
667     size,
668     attachment,
669     maskMode,
670     composite
671   };
672 
673   enum class LayerType : uint8_t {
674     Background = 0,
675     Mask
676   };
677 
678   explicit nsStyleImageLayers(LayerType aType);
679   nsStyleImageLayers(const nsStyleImageLayers &aSource);
~nsStyleImageLayersnsStyleImageLayers680   ~nsStyleImageLayers() {
681     MOZ_COUNT_DTOR(nsStyleImageLayers);
682   }
683 
684   static bool IsInitialPositionForLayerType(mozilla::Position aPosition, LayerType aType);
685 
686   struct Size;
687   friend struct Size;
688   struct Size {
689     struct Dimension : public nsStyleCoord::CalcValue {
ResolveLengthPercentagensStyleImageLayers::Size::Dimension690       nscoord ResolveLengthPercentage(nscoord aAvailable) const {
691         double d = double(mPercent) * double(aAvailable) + double(mLength);
692         if (d < 0.0) {
693           return 0;
694         }
695         return NSToCoordRoundWithClamp(float(d));
696       }
697     };
698     Dimension mWidth, mHeight;
699 
IsInitialValuensStyleImageLayers::Size700     bool IsInitialValue() const {
701       return mWidthType == eAuto && mHeightType == eAuto;
702     }
703 
ResolveWidthLengthPercentagensStyleImageLayers::Size704     nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
705       MOZ_ASSERT(mWidthType == eLengthPercentage,
706                  "resolving non-length/percent dimension!");
707       return mWidth.ResolveLengthPercentage(aBgPositioningArea.width);
708     }
709 
ResolveHeightLengthPercentagensStyleImageLayers::Size710     nscoord ResolveHeightLengthPercentage(const nsSize& aBgPositioningArea) const {
711       MOZ_ASSERT(mHeightType == eLengthPercentage,
712                  "resolving non-length/percent dimension!");
713       return mHeight.ResolveLengthPercentage(aBgPositioningArea.height);
714     }
715 
716     // Except for eLengthPercentage, Dimension types which might change
717     // how a layer is painted when the corresponding frame's dimensions
718     // change *must* precede all dimension types which are agnostic to
719     // frame size; see DependsOnDependsOnPositioningAreaSizeSize.
720     enum DimensionType {
721       // If one of mWidth and mHeight is eContain or eCover, then both are.
722       // NOTE: eContain and eCover *must* be equal to NS_STYLE_BG_SIZE_CONTAIN
723       // and NS_STYLE_BG_SIZE_COVER (in kBackgroundSizeKTable).
724       eContain, eCover,
725 
726       eAuto,
727       eLengthPercentage,
728       eDimensionType_COUNT
729     };
730     uint8_t mWidthType, mHeightType;
731 
732     // True if the effective image size described by this depends on the size of
733     // the corresponding frame, when aImage (which must not have null type) is
734     // the background image.
735     bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
736 
737     // Initialize nothing
SizensStyleImageLayers::Size738     Size() {}
739 
740     // Initialize to initial values
741     void SetInitialValues();
742 
743     bool operator==(const Size& aOther) const;
744     bool operator!=(const Size& aOther) const {
745       return !(*this == aOther);
746     }
747   };
748 
749   struct Repeat;
750   friend struct Repeat;
751   struct Repeat {
752     uint8_t mXRepeat, mYRepeat;
753 
754     // Initialize nothing
RepeatnsStyleImageLayers::Repeat755     Repeat() {}
756 
IsInitialValuensStyleImageLayers::Repeat757     bool IsInitialValue() const {
758       return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT &&
759              mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
760     }
761 
DependsOnPositioningAreaSizensStyleImageLayers::Repeat762     bool DependsOnPositioningAreaSize() const {
763       return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_SPACE ||
764              mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_SPACE;
765     }
766 
767     // Initialize to initial values
SetInitialValuesnsStyleImageLayers::Repeat768     void SetInitialValues() {
769       mXRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
770       mYRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
771     }
772 
773     bool operator==(const Repeat& aOther) const {
774       return mXRepeat == aOther.mXRepeat &&
775              mYRepeat == aOther.mYRepeat;
776     }
777     bool operator!=(const Repeat& aOther) const {
778       return !(*this == aOther);
779     }
780   };
781 
782   struct Layer;
783   friend struct Layer;
784   struct Layer {
785     nsStyleImage  mImage;         // [reset]
786     RefPtr<mozilla::css::URLValueData> mSourceURI;  // [reset]
787                                   // mask-only property
788                                   // This property is used for mask layer only.
789                                   // For a background layer, it should always
790                                   // be the initial value, which is nullptr.
791                                   // Store mask-image URI so that we can resolve
792                                   // SVG mask path later.  (Might be a URLValue
793                                   // or an ImageValue.)
794     mozilla::Position mPosition;  // [reset]
795     Size          mSize;          // [reset]
796     uint8_t       mClip;          // [reset] See nsStyleConsts.h
797     MOZ_INIT_OUTSIDE_CTOR
798       uint8_t     mOrigin;        // [reset] See nsStyleConsts.h
799     uint8_t       mAttachment;    // [reset] See nsStyleConsts.h
800                                   // background-only property
801                                   // This property is used for background layer
802                                   // only. For a mask layer, it should always
803                                   // be the initial value, which is
804                                   // NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL.
805     uint8_t       mBlendMode;     // [reset] See nsStyleConsts.h
806                                   // background-only property
807                                   // This property is used for background layer
808                                   // only. For a mask layer, it should always
809                                   // be the initial value, which is
810                                   // NS_STYLE_BLEND_NORMAL.
811     uint8_t       mComposite;     // [reset] See nsStyleConsts.h
812                                   // mask-only property
813                                   // This property is used for mask layer only.
814                                   // For a background layer, it should always
815                                   // be the initial value, which is
816                                   // NS_STYLE_COMPOSITE_MODE_ADD.
817     uint8_t       mMaskMode;      // [reset] See nsStyleConsts.h
818                                   // mask-only property
819                                   // This property is used for mask layer only.
820                                   // For a background layer, it should always
821                                   // be the initial value, which is
822                                   // NS_STYLE_MASK_MODE_MATCH_SOURCE.
823     Repeat        mRepeat;        // [reset] See nsStyleConsts.h
824 
825     // This constructor does not initialize mRepeat or mOrigin and Initialize()
826     // must be called to do that.
827     Layer();
828     ~Layer();
829 
830     // Initialize mRepeat and mOrigin by specified layer type
831     void Initialize(LayerType aType);
832 
ResolveImagensStyleImageLayers::Layer833     void ResolveImage(nsPresContext* aContext) {
834       if (mImage.GetType() == eStyleImageType_Image) {
835         mImage.ResolveImage(aContext);
836       }
837     }
838 
839     // True if the rendering of this layer might change when the size
840     // of the background positioning area changes.  This is true for any
841     // non-solid-color background whose position or size depends on
842     // the size of the positioning area.  It's also true for SVG images
843     // whose root <svg> node has a viewBox.
844     bool RenderingMightDependOnPositioningAreaSizeChange() const;
845 
846     // Compute the change hint required by changes in just this layer.
847     nsChangeHint CalcDifference(const Layer& aNewLayer) const;
848 
849     // An equality operator that compares the images using URL-equality
850     // rather than pointer-equality.
851     bool operator==(const Layer& aOther) const;
852     bool operator!=(const Layer& aOther) const {
853       return !(*this == aOther);
854     }
855   };
856 
857   // The (positive) number of computed values of each property, since
858   // the lengths of the lists are independent.
859   uint32_t mAttachmentCount,
860            mClipCount,
861            mOriginCount,
862            mRepeatCount,
863            mPositionXCount,
864            mPositionYCount,
865            mImageCount,
866            mSizeCount,
867            mMaskModeCount,
868            mBlendModeCount,
869            mCompositeCount;
870 
871   // Layers are stored in an array, matching the top-to-bottom order in
872   // which they are specified in CSS.  The number of layers to be used
873   // should come from the background-image property.  We create
874   // additional |Layer| objects for *any* property, not just
875   // background-image.  This means that the bottommost layer that
876   // callers in layout care about (which is also the one whose
877   // background-clip applies to the background-color) may not be last
878   // layer.  In layers below the bottom layer, properties will be
879   // uninitialized unless their count, above, indicates that they are
880   // present.
881   nsStyleAutoArray<Layer> mLayers;
882 
BottomLayernsStyleImageLayers883   const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
884 
ResolveImagesnsStyleImageLayers885   void ResolveImages(nsPresContext* aContext) {
886     for (uint32_t i = 0; i < mImageCount; ++i) {
887       mLayers[i].ResolveImage(aContext);
888     }
889   }
890 
891   nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
892                               nsStyleImageLayers::LayerType aType) const;
893 
894   bool HasLayerWithImage() const;
895   nsStyleImageLayers& operator=(const nsStyleImageLayers& aOther);
896 
897   static const nsCSSPropertyID kBackgroundLayerTable[];
898   static const nsCSSPropertyID kMaskLayerTable[];
899 
900   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
901     for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
902   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
903     NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < (layers_).mImageCount, "Invalid layer start!"); \
904     NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
905     for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
906 };
907 
908 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
909   explicit nsStyleBackground(StyleStructContext aContext);
910   nsStyleBackground(const nsStyleBackground& aOther);
911   ~nsStyleBackground();
912 
913   // Resolves and tracks the images in mImage.  Only called with a Servo-backed
914   // style system, where those images must be resolved later than the OMT
915   // nsStyleBackground constructor call.
916   void FinishStyle(nsPresContext* aPresContext);
917 
newnsStyleBackground918   void* operator new(size_t sz, nsStyleBackground* aSelf) { return aSelf; }
newnsStyleBackground919   void* operator new(size_t sz, nsPresContext* aContext) {
920     return aContext->PresShell()->
921       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
922   }
923   void Destroy(nsPresContext* aContext);
924 
925   nsChangeHint CalcDifference(const nsStyleBackground& aNewData) const;
MaxDifferencensStyleBackground926   static nsChangeHint MaxDifference() {
927      return nsChangeHint_UpdateEffects |
928            nsChangeHint_RepaintFrame |
929            nsChangeHint_UpdateBackgroundPosition |
930            nsChangeHint_NeutralChange;
931   }
DifferenceAlwaysHandledForDescendantsnsStyleBackground932   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
933     // CalcDifference never returns the reflow hints that are sometimes
934     // handled for descendants at all.
935     return nsChangeHint(0);
936   }
937 
938   // True if this background is completely transparent.
939   bool IsTransparent() const;
940 
941   // We have to take slower codepaths for fixed background attachment,
942   // but we don't want to do that when there's no image.
943   // Not inline because it uses an nsCOMPtr<imgIRequest>
944   // FIXME: Should be in nsStyleStructInlines.h.
945   bool HasFixedBackground(nsIFrame* aFrame) const;
946 
947   // Checks to see if this has a non-empty image with "local" attachment.
948   // This is defined in nsStyleStructInlines.h.
949   inline bool HasLocalBackground() const;
950 
BottomLayernsStyleBackground951   const nsStyleImageLayers::Layer& BottomLayer() const { return mImage.BottomLayer(); }
952 
953   nsStyleImageLayers mImage;
954   nscolor mBackgroundColor;       // [reset]
955 };
956 
957 #define NS_SPACING_MARGIN   0
958 #define NS_SPACING_PADDING  1
959 #define NS_SPACING_BORDER   2
960 
961 
962 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin
963 {
964   explicit nsStyleMargin(StyleStructContext aContext);
965   nsStyleMargin(const nsStyleMargin& aMargin);
~nsStyleMarginnsStyleMargin966   ~nsStyleMargin() {
967     MOZ_COUNT_DTOR(nsStyleMargin);
968   }
FinishStylensStyleMargin969   void FinishStyle(nsPresContext* aPresContext) {}
970 
newnsStyleMargin971   void* operator new(size_t sz, nsStyleMargin* aSelf) { return aSelf; }
newnsStyleMargin972   void* operator new(size_t sz, nsPresContext* aContext) {
973     return aContext->PresShell()->
974       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz);
975   }
976   void Destroy(nsPresContext* aContext);
977 
978   nsChangeHint CalcDifference(const nsStyleMargin& aNewData) const;
MaxDifferencensStyleMargin979   static nsChangeHint MaxDifference() {
980     return nsChangeHint_NeedReflow |
981            nsChangeHint_ReflowChangesSizeOrPosition |
982            nsChangeHint_ClearAncestorIntrinsics;
983   }
DifferenceAlwaysHandledForDescendantsnsStyleMargin984   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
985     // CalcDifference can return all of the reflow hints sometimes not
986     // handled for descendants as hints not handled for descendants.
987     return nsChangeHint(0);
988   }
989 
GetMarginnsStyleMargin990   bool GetMargin(nsMargin& aMargin) const
991   {
992     if (!mMargin.ConvertsToLength()) {
993       return false;
994     }
995 
996     NS_FOR_CSS_SIDES(side) {
997       aMargin.Side(side) = mMargin.ToLength(side);
998     }
999     return true;
1000   }
1001 
1002   // Return true if either the start or end side in the axis is 'auto'.
1003   // (defined in WritingModes.h since we need the full WritingMode type)
1004   inline bool HasBlockAxisAuto(mozilla::WritingMode aWM) const;
1005   inline bool HasInlineAxisAuto(mozilla::WritingMode aWM) const;
1006 
1007   nsStyleSides  mMargin; // [reset] coord, percent, calc, auto
1008 };
1009 
1010 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding
1011 {
1012   explicit nsStylePadding(StyleStructContext aContext);
1013   nsStylePadding(const nsStylePadding& aPadding);
~nsStylePaddingnsStylePadding1014   ~nsStylePadding() {
1015     MOZ_COUNT_DTOR(nsStylePadding);
1016   }
FinishStylensStylePadding1017   void FinishStyle(nsPresContext* aPresContext) {}
1018 
newnsStylePadding1019   void* operator new(size_t sz, nsStylePadding* aSelf) { return aSelf; }
newnsStylePadding1020   void* operator new(size_t sz, nsPresContext* aContext) {
1021     return aContext->PresShell()->
1022       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz);
1023   }
1024   void Destroy(nsPresContext* aContext);
1025 
1026   nsChangeHint CalcDifference(const nsStylePadding& aNewData) const;
MaxDifferencensStylePadding1027   static nsChangeHint MaxDifference() {
1028     return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
1029   }
DifferenceAlwaysHandledForDescendantsnsStylePadding1030   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1031     // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as
1032     // a hint not handled for descendants.  We could (and perhaps
1033     // should) return nsChangeHint_NeedReflow and
1034     // nsChangeHint_ReflowChangesSizeOrPosition as always handled for
1035     // descendants, but since they're always returned in conjunction
1036     // with nsChangeHint_ClearAncestorIntrinsics (which is not), it
1037     // won't ever lead to any optimization in
1038     // nsStyleContext::CalcStyleDifference.
1039     return nsChangeHint(0);
1040   }
1041 
1042   nsStyleSides  mPadding;         // [reset] coord, percent, calc
1043 
IsWidthDependentnsStylePadding1044   bool IsWidthDependent() const {
1045     return !mPadding.ConvertsToLength();
1046   }
1047 
GetPaddingnsStylePadding1048   bool GetPadding(nsMargin& aPadding) const
1049   {
1050     if (!mPadding.ConvertsToLength()) {
1051       return false;
1052     }
1053 
1054     NS_FOR_CSS_SIDES(side) {
1055       // Clamp negative calc() to 0.
1056       aPadding.Side(side) = std::max(mPadding.ToLength(side), 0);
1057     }
1058     return true;
1059   }
1060 };
1061 
1062 struct nsBorderColors
1063 {
1064   nsBorderColors* mNext;
1065   nscolor mColor;
1066 
nsBorderColorsnsBorderColors1067   nsBorderColors() : mNext(nullptr), mColor(NS_RGB(0,0,0)) {}
nsBorderColorsnsBorderColors1068   explicit nsBorderColors(const nscolor& aColor) : mNext(nullptr), mColor(aColor) {}
1069   ~nsBorderColors();
1070 
ClonensBorderColors1071   nsBorderColors* Clone() const { return Clone(true); }
1072 
EqualnsBorderColors1073   static bool Equal(const nsBorderColors* c1,
1074                       const nsBorderColors* c2) {
1075     if (c1 == c2) {
1076       return true;
1077     }
1078     while (c1 && c2) {
1079       if (c1->mColor != c2->mColor) {
1080         return false;
1081       }
1082       c1 = c1->mNext;
1083       c2 = c2->mNext;
1084     }
1085     // both should be nullptr if these are equal, otherwise one
1086     // has more colors than another
1087     return !c1 && !c2;
1088   }
1089 
1090 private:
1091   nsBorderColors* Clone(bool aDeep) const;
1092 };
1093 
1094 struct nsCSSShadowItem
1095 {
1096   nscoord mXOffset;
1097   nscoord mYOffset;
1098   nscoord mRadius;
1099   nscoord mSpread;
1100 
1101   nscolor      mColor;
1102   bool mHasColor; // Whether mColor should be used
1103   bool mInset;
1104 
nsCSSShadowItemnsCSSShadowItem1105   nsCSSShadowItem() : mHasColor(false) {
1106     MOZ_COUNT_CTOR(nsCSSShadowItem);
1107   }
~nsCSSShadowItemnsCSSShadowItem1108   ~nsCSSShadowItem() {
1109     MOZ_COUNT_DTOR(nsCSSShadowItem);
1110   }
1111 
1112   bool operator==(const nsCSSShadowItem& aOther) const {
1113     return (mXOffset == aOther.mXOffset &&
1114             mYOffset == aOther.mYOffset &&
1115             mRadius == aOther.mRadius &&
1116             mHasColor == aOther.mHasColor &&
1117             mSpread == aOther.mSpread &&
1118             mInset == aOther.mInset &&
1119             (!mHasColor || mColor == aOther.mColor));
1120   }
1121   bool operator!=(const nsCSSShadowItem& aOther) const {
1122     return !(*this == aOther);
1123   }
1124 };
1125 
1126 class nsCSSShadowArray final
1127 {
1128 public:
new(size_t aBaseSize,uint32_t aArrayLen)1129   void* operator new(size_t aBaseSize, uint32_t aArrayLen) {
1130     // We can allocate both this nsCSSShadowArray and the
1131     // actual array in one allocation. The amount of memory to
1132     // allocate is equal to the class's size + the number of bytes for all
1133     // but the first array item (because aBaseSize includes one
1134     // item, see the private declarations)
1135     return ::operator new(aBaseSize +
1136                           (aArrayLen - 1) * sizeof(nsCSSShadowItem));
1137   }
1138 
nsCSSShadowArray(uint32_t aArrayLen)1139   explicit nsCSSShadowArray(uint32_t aArrayLen) :
1140     mLength(aArrayLen)
1141   {
1142     MOZ_COUNT_CTOR(nsCSSShadowArray);
1143     for (uint32_t i = 1; i < mLength; ++i) {
1144       // Make sure we call the constructors of each nsCSSShadowItem
1145       // (the first one is called for us because we declared it under private)
1146       new (&mArray[i]) nsCSSShadowItem();
1147     }
1148   }
1149 
1150 private:
1151   // Private destructor, to discourage deletion outside of Release():
~nsCSSShadowArray()1152   ~nsCSSShadowArray() {
1153     MOZ_COUNT_DTOR(nsCSSShadowArray);
1154     for (uint32_t i = 1; i < mLength; ++i) {
1155       mArray[i].~nsCSSShadowItem();
1156     }
1157   }
1158 
1159 public:
Length()1160   uint32_t Length() const { return mLength; }
ShadowAt(uint32_t i)1161   nsCSSShadowItem* ShadowAt(uint32_t i) {
1162     MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!");
1163     return &mArray[i];
1164   }
ShadowAt(uint32_t i)1165   const nsCSSShadowItem* ShadowAt(uint32_t i) const {
1166     MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!");
1167     return &mArray[i];
1168   }
1169 
HasShadowWithInset(bool aInset)1170   bool HasShadowWithInset(bool aInset) {
1171     for (uint32_t i = 0; i < mLength; ++i) {
1172       if (mArray[i].mInset == aInset) {
1173         return true;
1174       }
1175     }
1176     return false;
1177   }
1178 
1179   bool operator==(const nsCSSShadowArray& aOther) const {
1180     if (mLength != aOther.Length()) {
1181       return false;
1182     }
1183 
1184     for (uint32_t i = 0; i < mLength; ++i) {
1185       if (ShadowAt(i) != aOther.ShadowAt(i)) {
1186         return false;
1187       }
1188     }
1189 
1190     return true;
1191   }
1192 
1193   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSShadowArray)
1194 
1195 private:
1196   uint32_t mLength;
1197   nsCSSShadowItem mArray[1]; // This MUST be the last item
1198 };
1199 
1200 // Border widths are rounded to the nearest-below integer number of pixels,
1201 // but values between zero and one device pixels are always rounded up to
1202 // one device pixel.
1203 #define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
1204   ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
1205 // Outline offset is rounded to the nearest integer number of pixels, but values
1206 // between zero and one device pixels are always rounded up to one device pixel.
1207 // Note that the offset can be negative.
1208 #define NS_ROUND_OFFSET_TO_PIXELS(l,tpp) \
1209   (((l) == 0) ? 0 : \
1210     ((l) > 0) ? std::max( (tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) : \
1211                 std::min(-(tpp), ((l) - ((tpp) / 2)) / (tpp) * (tpp)))
1212 
1213 // Returns if the given border style type is visible or not
IsVisibleBorderStyle(uint8_t aStyle)1214 static bool IsVisibleBorderStyle(uint8_t aStyle)
1215 {
1216   return (aStyle != NS_STYLE_BORDER_STYLE_NONE &&
1217           aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
1218 }
1219 
1220 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
1221 {
1222   explicit nsStyleBorder(StyleStructContext aContext);
1223   nsStyleBorder(const nsStyleBorder& aBorder);
1224   ~nsStyleBorder();
1225 
1226   // Resolves and tracks mBorderImageSource.  Only called with a Servo-backed
1227   // style system, where those images must be resolved later than the OMT
1228   // nsStyleBorder constructor call.
1229   void FinishStyle(nsPresContext* aPresContext);
1230 
newnsStyleBorder1231   void* operator new(size_t sz, nsStyleBorder* aSelf) { return aSelf; }
newnsStyleBorder1232   void* operator new(size_t sz, nsPresContext* aContext) {
1233     return aContext->PresShell()->
1234       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
1235   }
1236   void Destroy(nsPresContext* aContext);
1237 
1238   nsChangeHint CalcDifference(const nsStyleBorder& aNewData) const;
MaxDifferencensStyleBorder1239   static nsChangeHint MaxDifference() {
1240     return NS_STYLE_HINT_REFLOW |
1241            nsChangeHint_UpdateOverflow |
1242            nsChangeHint_BorderStyleNoneChange |
1243            nsChangeHint_NeutralChange;
1244   }
DifferenceAlwaysHandledForDescendantsnsStyleBorder1245   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1246     // CalcDifference never returns the reflow hints that are sometimes
1247     // handled for descendants as hints not handled for descendants.
1248     return nsChangeHint_NeedReflow |
1249            nsChangeHint_ReflowChangesSizeOrPosition |
1250            nsChangeHint_ClearAncestorIntrinsics;
1251   }
1252 
EnsureBorderColorsnsStyleBorder1253   void EnsureBorderColors() {
1254     if (!mBorderColors) {
1255       mBorderColors = new nsBorderColors*[4];
1256       if (mBorderColors) {
1257         for (int32_t i = 0; i < 4; i++) {
1258           mBorderColors[i] = nullptr;
1259         }
1260       }
1261     }
1262   }
1263 
ClearBorderColorsnsStyleBorder1264   void ClearBorderColors(mozilla::css::Side aSide) {
1265     if (mBorderColors && mBorderColors[aSide]) {
1266       delete mBorderColors[aSide];
1267       mBorderColors[aSide] = nullptr;
1268     }
1269   }
1270 
1271   // Return whether aStyle is a visible style.  Invisible styles cause
1272   // the relevant computed border width to be 0.
1273   // Note that this does *not* consider the effects of 'border-image':
1274   // if border-style is none, but there is a loaded border image,
1275   // HasVisibleStyle will be false even though there *is* a border.
HasVisibleStylensStyleBorder1276   bool HasVisibleStyle(mozilla::css::Side aSide) const
1277   {
1278     return IsVisibleBorderStyle(mBorderStyle[aSide]);
1279   }
1280 
1281   // aBorderWidth is in twips
SetBorderWidthnsStyleBorder1282   void SetBorderWidth(mozilla::css::Side aSide, nscoord aBorderWidth)
1283   {
1284     nscoord roundedWidth =
1285       NS_ROUND_BORDER_TO_PIXELS(aBorderWidth, mTwipsPerPixel);
1286     mBorder.Side(aSide) = roundedWidth;
1287     if (HasVisibleStyle(aSide)) {
1288       mComputedBorder.Side(aSide) = roundedWidth;
1289     }
1290   }
1291 
1292   // Get the computed border (plus rounding).  This does consider the
1293   // effects of 'border-style: none', but does not consider
1294   // 'border-image'.
GetComputedBordernsStyleBorder1295   const nsMargin& GetComputedBorder() const
1296   {
1297     return mComputedBorder;
1298   }
1299 
HasBordernsStyleBorder1300   bool HasBorder() const
1301   {
1302     return mComputedBorder != nsMargin(0,0,0,0) || !mBorderImageSource.IsEmpty();
1303   }
1304 
1305   // Get the actual border width for a particular side, in appunits.  Note that
1306   // this is zero if and only if there is no border to be painted for this
1307   // side.  That is, this value takes into account the border style and the
1308   // value is rounded to the nearest device pixel by NS_ROUND_BORDER_TO_PIXELS.
GetComputedBorderWidthnsStyleBorder1309   nscoord GetComputedBorderWidth(mozilla::css::Side aSide) const
1310   {
1311     return GetComputedBorder().Side(aSide);
1312   }
1313 
GetBorderStylensStyleBorder1314   uint8_t GetBorderStyle(mozilla::css::Side aSide) const
1315   {
1316     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
1317     return mBorderStyle[aSide];
1318   }
1319 
SetBorderStylensStyleBorder1320   void SetBorderStyle(mozilla::css::Side aSide, uint8_t aStyle)
1321   {
1322     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
1323     mBorderStyle[aSide] = aStyle;
1324     mComputedBorder.Side(aSide) =
1325       (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
1326   }
1327 
IsBorderImageLoadednsStyleBorder1328   inline bool IsBorderImageLoaded() const
1329   {
1330     return mBorderImageSource.IsLoaded();
1331   }
1332 
ResolveImagensStyleBorder1333   void ResolveImage(nsPresContext* aContext)
1334   {
1335     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
1336       mBorderImageSource.ResolveImage(aContext);
1337     }
1338   }
1339 
1340   nsMargin GetImageOutset() const;
1341 
GetCompositeColorsnsStyleBorder1342   void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
1343   {
1344     if (!mBorderColors) {
1345       *aColors = nullptr;
1346     } else {
1347       *aColors = mBorderColors[aIndex];
1348     }
1349   }
1350 
AppendBorderColornsStyleBorder1351   void AppendBorderColor(int32_t aIndex, nscolor aColor)
1352   {
1353     NS_ASSERTION(aIndex >= 0 && aIndex <= 3, "bad side for composite border color");
1354     nsBorderColors* colorEntry = new nsBorderColors(aColor);
1355     if (!mBorderColors[aIndex]) {
1356       mBorderColors[aIndex] = colorEntry;
1357     } else {
1358       nsBorderColors* last = mBorderColors[aIndex];
1359       while (last->mNext) {
1360         last = last->mNext;
1361       }
1362       last->mNext = colorEntry;
1363     }
1364   }
1365 
GetBorderImageRequestnsStyleBorder1366   imgIRequest* GetBorderImageRequest() const
1367   {
1368     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
1369       return mBorderImageSource.GetImageData();
1370     }
1371     return nullptr;
1372   }
1373 
1374 public:
1375   nsBorderColors** mBorderColors;     // [reset] composite (stripe) colors
1376   nsStyleCorners mBorderRadius;       // [reset] coord, percent
1377   nsStyleImage   mBorderImageSource;  // [reset]
1378   nsStyleSides   mBorderImageSlice;   // [reset] factor, percent
1379   nsStyleSides   mBorderImageWidth;   // [reset] length, factor, percent, auto
1380   nsStyleSides   mBorderImageOutset;  // [reset] length, factor
1381 
1382   uint8_t        mBorderImageFill;    // [reset]
1383   uint8_t        mBorderImageRepeatH; // [reset] see nsStyleConsts.h
1384   uint8_t        mBorderImageRepeatV; // [reset]
1385   mozilla::StyleFloatEdge mFloatEdge; // [reset]
1386   mozilla::StyleBoxDecorationBreak mBoxDecorationBreak; // [reset]
1387 
1388 protected:
1389   uint8_t       mBorderStyle[4];  // [reset] See nsStyleConsts.h
1390 
1391 public:
1392   // [reset] the colors to use for a simple border.
1393   // not used for -moz-border-colors
1394   union {
1395     struct {
1396       mozilla::StyleComplexColor mBorderTopColor;
1397       mozilla::StyleComplexColor mBorderRightColor;
1398       mozilla::StyleComplexColor mBorderBottomColor;
1399       mozilla::StyleComplexColor mBorderLeftColor;
1400     };
1401     mozilla::StyleComplexColor mBorderColor[4];
1402   };
1403 
1404 protected:
1405   // mComputedBorder holds the CSS2.1 computed border-width values.
1406   // In particular, these widths take into account the border-style
1407   // for the relevant side, and the values are rounded to the nearest
1408   // device pixel (which is not part of the definition of computed
1409   // values). The presence or absence of a border-image does not
1410   // affect border-width values.
1411   nsMargin      mComputedBorder;
1412 
1413   // mBorder holds the nscoord values for the border widths as they
1414   // would be if all the border-style values were visible (not hidden
1415   // or none).  This member exists so that when we create structs
1416   // using the copy constructor during style resolution the new
1417   // structs will know what the specified values of the border were in
1418   // case they have more specific rules setting the border style.
1419   //
1420   // Note that this isn't quite the CSS specified value, since this
1421   // has had the enumerated border widths converted to lengths, and
1422   // all lengths converted to twips.  But it's not quite the computed
1423   // value either. The values are rounded to the nearest device pixel.
1424   nsMargin      mBorder;
1425 
1426 private:
1427   nscoord       mTwipsPerPixel;
1428 
1429   nsStyleBorder& operator=(const nsStyleBorder& aOther) = delete;
1430 };
1431 
1432 #define ASSERT_BORDER_COLOR_FIELD(side_)                          \
1433   static_assert(offsetof(nsStyleBorder, mBorder##side_##Color) == \
1434                   offsetof(nsStyleBorder, mBorderColor) +         \
1435                     size_t(mozilla::eSide##side_) *               \
1436                     sizeof(mozilla::StyleComplexColor),           \
1437                 "mBorder" #side_ "Color must be at same offset "  \
1438                 "as mBorderColor[mozilla::eSide" #side_ "]")
1439 ASSERT_BORDER_COLOR_FIELD(Top);
1440 ASSERT_BORDER_COLOR_FIELD(Right);
1441 ASSERT_BORDER_COLOR_FIELD(Bottom);
1442 ASSERT_BORDER_COLOR_FIELD(Left);
1443 #undef ASSERT_BORDER_COLOR_FIELD
1444 
1445 
1446 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline
1447 {
1448   explicit nsStyleOutline(StyleStructContext aContext);
1449   nsStyleOutline(const nsStyleOutline& aOutline);
~nsStyleOutlinensStyleOutline1450   ~nsStyleOutline() {
1451     MOZ_COUNT_DTOR(nsStyleOutline);
1452   }
FinishStylensStyleOutline1453   void FinishStyle(nsPresContext* aPresContext) {}
1454 
newnsStyleOutline1455   void* operator new(size_t sz, nsStyleOutline* aSelf) { return aSelf; }
newnsStyleOutline1456   void* operator new(size_t sz, nsPresContext* aContext) {
1457     return aContext->PresShell()->
1458       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleOutline, sz);
1459   }
DestroynsStyleOutline1460   void Destroy(nsPresContext* aContext) {
1461     this->~nsStyleOutline();
1462     aContext->PresShell()->
1463       FreeByObjectID(mozilla::eArenaObjectID_nsStyleOutline, this);
1464   }
1465 
1466   void RecalcData();
1467   nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
MaxDifferencensStyleOutline1468   static nsChangeHint MaxDifference() {
1469     return nsChangeHint_UpdateOverflow |
1470            nsChangeHint_SchedulePaint |
1471            nsChangeHint_RepaintFrame |
1472            nsChangeHint_NeutralChange;
1473   }
DifferenceAlwaysHandledForDescendantsnsStyleOutline1474   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1475     // CalcDifference never returns the reflow hints that are sometimes
1476     // handled for descendants at all.
1477     return nsChangeHint(0);
1478   }
1479 
1480   nsStyleCorners  mOutlineRadius; // [reset] coord, percent, calc
1481 
1482   // This is the specified value of outline-width, but with length values
1483   // computed to absolute.  mActualOutlineWidth stores the outline-width
1484   // value used by layout.  (We must store mOutlineWidth for the same
1485   // style struct resolution reasons that we do nsStyleBorder::mBorder;
1486   // see that field's comment.)
1487   nsStyleCoord  mOutlineWidth;    // [reset] coord, enum (see nsStyleConsts.h)
1488   nscoord       mOutlineOffset;   // [reset]
1489   mozilla::StyleComplexColor mOutlineColor; // [reset]
1490   uint8_t       mOutlineStyle;    // [reset] See nsStyleConsts.h
1491 
GetOutlineWidthnsStyleOutline1492   nscoord GetOutlineWidth() const
1493   {
1494     return mActualOutlineWidth;
1495   }
1496 
1497 protected:
1498   // The actual value of outline-width is the computed value (an absolute
1499   // length, forced to zero when outline-style is none) rounded to device
1500   // pixels.  This is the value used by layout.
1501   nscoord       mActualOutlineWidth;
1502   nscoord       mTwipsPerPixel;
1503 };
1504 
1505 
1506 /**
1507  * An object that allows sharing of arrays that store 'quotes' property
1508  * values.  This is particularly important for inheritance, where we want
1509  * to share the same 'quotes' value with a parent style context.
1510  */
1511 class nsStyleQuoteValues
1512 {
1513 public:
1514   typedef nsTArray<std::pair<nsString, nsString>> QuotePairArray;
1515   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleQuoteValues);
1516   QuotePairArray mQuotePairs;
1517 
1518 private:
~nsStyleQuoteValues()1519   ~nsStyleQuoteValues() {}
1520 };
1521 
1522 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
1523 {
1524   explicit nsStyleList(StyleStructContext aContext);
1525   nsStyleList(const nsStyleList& aStyleList);
1526   ~nsStyleList();
1527 
1528   void FinishStyle(nsPresContext* aPresContext);
1529 
newnsStyleList1530   void* operator new(size_t sz, nsStyleList* aSelf) { return aSelf; }
newnsStyleList1531   void* operator new(size_t sz, nsPresContext* aContext) {
1532     return aContext->PresShell()->
1533       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz);
1534   }
DestroynsStyleList1535   void Destroy(nsPresContext* aContext) {
1536     this->~nsStyleList();
1537     aContext->PresShell()->
1538       FreeByObjectID(mozilla::eArenaObjectID_nsStyleList, this);
1539   }
1540 
1541   nsChangeHint CalcDifference(const nsStyleList& aNewData) const;
MaxDifferencensStyleList1542   static nsChangeHint MaxDifference() {
1543     return nsChangeHint_ReconstructFrame |
1544            NS_STYLE_HINT_REFLOW;
1545   }
DifferenceAlwaysHandledForDescendantsnsStyleList1546   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1547     // CalcDifference never returns the reflow hints that are sometimes
1548     // handled for descendants as hints not handled for descendants.
1549     return nsChangeHint_NeedReflow |
1550            nsChangeHint_ReflowChangesSizeOrPosition |
1551            nsChangeHint_ClearAncestorIntrinsics;
1552   }
1553 
ShutdownnsStyleList1554   static void Shutdown() {
1555     sInitialQuotes = nullptr;
1556     sNoneQuotes = nullptr;
1557   }
1558 
GetListStyleImagensStyleList1559   imgRequestProxy* GetListStyleImage() const
1560   {
1561     return mListStyleImage ? mListStyleImage->get() : nullptr;
1562   }
1563 
GetListStyleTypensStyleList1564   void GetListStyleType(nsSubstring& aType) const { mCounterStyle->GetStyleName(aType); }
GetCounterStylensStyleList1565   mozilla::CounterStyle* GetCounterStyle() const
1566   {
1567     return mCounterStyle.get();
1568   }
SetCounterStylensStyleList1569   void SetCounterStyle(mozilla::CounterStyle* aStyle)
1570   {
1571     // NB: This function is called off-main-thread during parallel restyle, but
1572     // only with builtin styles that use dummy refcounting.
1573     MOZ_ASSERT(NS_IsMainThread() || !aStyle->IsDependentStyle());
1574     mCounterStyle = aStyle;
1575   }
SetListStyleTypensStyleList1576   void SetListStyleType(const nsSubstring& aType,
1577                         nsPresContext* aPresContext)
1578   {
1579     SetCounterStyle(aPresContext->CounterStyleManager()->BuildCounterStyle(aType));
1580   }
1581 
1582   const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
1583 
1584   void SetQuotesInherit(const nsStyleList* aOther);
1585   void SetQuotesInitial();
1586   void SetQuotesNone();
1587   void SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues);
1588 
1589   uint8_t mListStylePosition;                  // [inherited]
1590   RefPtr<nsStyleImageRequest> mListStyleImage; // [inherited]
1591 private:
1592   RefPtr<mozilla::CounterStyle> mCounterStyle; // [inherited]
1593   RefPtr<nsStyleQuoteValues> mQuotes;   // [inherited]
1594   nsStyleList& operator=(const nsStyleList& aOther) = delete;
1595 public:
1596   nsRect        mImageRegion;           // [inherited] the rect to use within an image
1597 
1598 private:
1599   // nsStyleQuoteValues objects representing two common values, for sharing.
1600   static mozilla::StaticRefPtr<nsStyleQuoteValues> sInitialQuotes;
1601   static mozilla::StaticRefPtr<nsStyleQuoteValues> sNoneQuotes;
1602 };
1603 
1604 struct nsStyleGridLine
1605 {
1606   // http://dev.w3.org/csswg/css-grid/#typedef-grid-line
1607   // XXXmats we could optimize memory size here
1608   bool mHasSpan;
1609   int32_t mInteger;  // 0 means not provided
1610   nsString mLineName;  // Empty string means not provided.
1611 
1612   // These are the limits that we choose to clamp grid line numbers to.
1613   // http://dev.w3.org/csswg/css-grid/#overlarge-grids
1614   // mInteger is clamped to this range:
1615   static const int32_t kMinLine = -10000;
1616   static const int32_t kMaxLine = 10000;
1617 
nsStyleGridLinensStyleGridLine1618   nsStyleGridLine()
1619     : mHasSpan(false)
1620     , mInteger(0)
1621     // mLineName get its default constructor, the empty string
1622   {
1623   }
1624 
nsStyleGridLinensStyleGridLine1625   nsStyleGridLine(const nsStyleGridLine& aOther)
1626   {
1627     (*this) = aOther;
1628   }
1629 
1630   void operator=(const nsStyleGridLine& aOther)
1631   {
1632     mHasSpan = aOther.mHasSpan;
1633     mInteger = aOther.mInteger;
1634     mLineName = aOther.mLineName;
1635   }
1636 
1637   bool operator!=(const nsStyleGridLine& aOther) const
1638   {
1639     return mHasSpan != aOther.mHasSpan ||
1640            mInteger != aOther.mInteger ||
1641            mLineName != aOther.mLineName;
1642   }
1643 
SetToIntegernsStyleGridLine1644   void SetToInteger(uint32_t value)
1645   {
1646     mHasSpan = false;
1647     mInteger = value;
1648     mLineName.Truncate();
1649   }
1650 
SetAutonsStyleGridLine1651   void SetAuto()
1652   {
1653     mHasSpan = false;
1654     mInteger = 0;
1655     mLineName.Truncate();
1656   }
1657 
IsAutonsStyleGridLine1658   bool IsAuto() const
1659   {
1660     bool haveInitialValues =  mInteger == 0 && mLineName.IsEmpty();
1661     MOZ_ASSERT(!(haveInitialValues && mHasSpan),
1662                "should not have 'span' when other components are "
1663                "at their initial values");
1664     return haveInitialValues;
1665   }
1666 };
1667 
1668 // Computed value of the grid-template-columns or grid-template-rows property
1669 // (but *not* grid-template-areas.)
1670 // http://dev.w3.org/csswg/css-grid/#track-sizing
1671 //
1672 // This represents either:
1673 // * none:
1674 //   mIsSubgrid is false, all three arrays are empty
1675 // * <track-list>:
1676 //   mIsSubgrid is false,
1677 //   mMinTrackSizingFunctions and mMaxTrackSizingFunctions
1678 //   are of identical non-zero size,
1679 //   and mLineNameLists is one element longer than that.
1680 //   (Delimiting N columns requires N+1 lines:
1681 //   one before each track, plus one at the very end.)
1682 //
1683 //   An omitted <line-names> is still represented in mLineNameLists,
1684 //   as an empty sub-array.
1685 //
1686 //   A <track-size> specified as a single <track-breadth> is represented
1687 //   as identical min and max sizing functions.
1688 //   A 'fit-content(size)' <track-size> is represented as eStyleUnit_None
1689 //   in the min sizing function and 'size' in the max sizing function.
1690 //
1691 //   The units for nsStyleCoord are:
1692 //   * eStyleUnit_Percent represents a <percentage>
1693 //   * eStyleUnit_FlexFraction represents a <flex> flexible fraction
1694 //   * eStyleUnit_Coord represents a <length>
1695 //   * eStyleUnit_Enumerated represents min-content or max-content
1696 // * subgrid <line-name-list>?:
1697 //   mIsSubgrid is true,
1698 //   mLineNameLists may or may not be empty,
1699 //   mMinTrackSizingFunctions and mMaxTrackSizingFunctions are empty.
1700 //
1701 // If mRepeatAutoIndex != -1 then that index is an <auto-repeat> and
1702 // mIsAutoFill == true means it's an 'auto-fill', otherwise 'auto-fit'.
1703 // mRepeatAutoLineNameListBefore is the list of line names before the track
1704 // size, mRepeatAutoLineNameListAfter the names after.  (They are empty
1705 // when there is no <auto-repeat> track, i.e. when mRepeatAutoIndex == -1).
1706 // When mIsSubgrid is true, mRepeatAutoLineNameListBefore contains the line
1707 // names and mRepeatAutoLineNameListAfter is empty.
1708 struct nsStyleGridTemplate
1709 {
1710   nsTArray<nsTArray<nsString>> mLineNameLists;
1711   nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
1712   nsTArray<nsStyleCoord> mMaxTrackSizingFunctions;
1713   nsTArray<nsString> mRepeatAutoLineNameListBefore;
1714   nsTArray<nsString> mRepeatAutoLineNameListAfter;
1715   int16_t mRepeatAutoIndex; // -1 or the track index for an auto-fill/fit track
1716   bool mIsAutoFill : 1;
1717   bool mIsSubgrid : 1;
1718 
nsStyleGridTemplatensStyleGridTemplate1719   nsStyleGridTemplate()
1720     : mRepeatAutoIndex(-1)
1721     , mIsAutoFill(false)
1722     , mIsSubgrid(false)
1723   {
1724   }
1725 
1726   inline bool operator!=(const nsStyleGridTemplate& aOther) const {
1727     return
1728       mIsSubgrid != aOther.mIsSubgrid ||
1729       mLineNameLists != aOther.mLineNameLists ||
1730       mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
1731       mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions ||
1732       mIsAutoFill != aOther.mIsAutoFill ||
1733       mRepeatAutoIndex != aOther.mRepeatAutoIndex ||
1734       mRepeatAutoLineNameListBefore != aOther.mRepeatAutoLineNameListBefore ||
1735       mRepeatAutoLineNameListAfter != aOther.mRepeatAutoLineNameListAfter;
1736   }
1737 
HasRepeatAutonsStyleGridTemplate1738   bool HasRepeatAuto() const {
1739     return mRepeatAutoIndex != -1;
1740   }
1741 
IsRepeatAutoIndexnsStyleGridTemplate1742   bool IsRepeatAutoIndex(uint32_t aIndex) const {
1743     MOZ_ASSERT(aIndex < uint32_t(2*nsStyleGridLine::kMaxLine));
1744     return int32_t(aIndex) == mRepeatAutoIndex;
1745   }
1746 };
1747 
1748 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
1749 {
1750   explicit nsStylePosition(StyleStructContext aContext);
1751   nsStylePosition(const nsStylePosition& aOther);
1752   ~nsStylePosition();
FinishStylensStylePosition1753   void FinishStyle(nsPresContext* aPresContext) {}
1754 
newnsStylePosition1755   void* operator new(size_t sz, nsStylePosition* aSelf) { return aSelf; }
newnsStylePosition1756   void* operator new(size_t sz, nsPresContext* aContext) {
1757     return aContext->PresShell()->
1758       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz);
1759   }
DestroynsStylePosition1760   void Destroy(nsPresContext* aContext) {
1761     this->~nsStylePosition();
1762     aContext->PresShell()->
1763       FreeByObjectID(mozilla::eArenaObjectID_nsStylePosition, this);
1764   }
1765 
1766   nsChangeHint CalcDifference(const nsStylePosition& aNewData,
1767                               const nsStyleVisibility* aOldStyleVisibility) const;
MaxDifferencensStylePosition1768   static nsChangeHint MaxDifference() {
1769     return NS_STYLE_HINT_REFLOW |
1770            nsChangeHint_NeutralChange |
1771            nsChangeHint_RecomputePosition |
1772            nsChangeHint_UpdateParentOverflow |
1773            nsChangeHint_UpdateComputedBSize;
1774   }
DifferenceAlwaysHandledForDescendantsnsStylePosition1775   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1776     // CalcDifference can return all of the reflow hints that are
1777     // sometimes handled for descendants as hints not handled for
1778     // descendants.
1779     return nsChangeHint(0);
1780   }
1781 
1782   /**
1783    * Return the used value for 'align-self' given our parent StyleContext
1784    * aParent (or null for the root).
1785    */
1786   uint8_t UsedAlignSelf(nsStyleContext* aParent) const;
1787 
1788   /**
1789    * Return the computed value for 'justify-items' given our parent StyleContext
1790    * aParent (or null for the root).
1791    */
1792   uint8_t ComputedJustifyItems(nsStyleContext* aParent) const;
1793 
1794   /**
1795    * Return the used value for 'justify-self' given our parent StyleContext
1796    * aParent (or null for the root).
1797    */
1798   uint8_t UsedJustifySelf(nsStyleContext* aParent) const;
1799 
1800   mozilla::Position mObjectPosition;    // [reset]
1801   nsStyleSides  mOffset;                // [reset] coord, percent, calc, auto
1802   nsStyleCoord  mWidth;                 // [reset] coord, percent, enum, calc, auto
1803   nsStyleCoord  mMinWidth;              // [reset] coord, percent, enum, calc
1804   nsStyleCoord  mMaxWidth;              // [reset] coord, percent, enum, calc, none
1805   nsStyleCoord  mHeight;                // [reset] coord, percent, calc, auto
1806   nsStyleCoord  mMinHeight;             // [reset] coord, percent, calc
1807   nsStyleCoord  mMaxHeight;             // [reset] coord, percent, calc, none
1808   nsStyleCoord  mFlexBasis;             // [reset] coord, percent, enum, calc, auto
1809   nsStyleCoord  mGridAutoColumnsMin;    // [reset] coord, percent, enum, calc, flex
1810   nsStyleCoord  mGridAutoColumnsMax;    // [reset] coord, percent, enum, calc, flex
1811   nsStyleCoord  mGridAutoRowsMin;       // [reset] coord, percent, enum, calc, flex
1812   nsStyleCoord  mGridAutoRowsMax;       // [reset] coord, percent, enum, calc, flex
1813   uint8_t       mGridAutoFlow;          // [reset] enumerated. See nsStyleConsts.h
1814   mozilla::StyleBoxSizing mBoxSizing;   // [reset] see nsStyleConsts.h
1815 
1816   uint16_t      mAlignContent;          // [reset] fallback value in the high byte
1817   uint8_t       mAlignItems;            // [reset] see nsStyleConsts.h
1818   uint8_t       mAlignSelf;             // [reset] see nsStyleConsts.h
1819   uint16_t      mJustifyContent;        // [reset] fallback value in the high byte
1820 private:
1821   friend class nsRuleNode;
1822 
1823   // mJustifyItems should only be read via ComputedJustifyItems(), which
1824   // lazily resolves its "auto" value. nsRuleNode needs direct access so
1825   // it can set mJustifyItems' value when populating this struct.
1826   uint8_t       mJustifyItems;          // [reset] see nsStyleConsts.h
1827 public:
1828   uint8_t       mJustifySelf;           // [reset] see nsStyleConsts.h
1829   uint8_t       mFlexDirection;         // [reset] see nsStyleConsts.h
1830   uint8_t       mFlexWrap;              // [reset] see nsStyleConsts.h
1831   uint8_t       mObjectFit;             // [reset] see nsStyleConsts.h
1832   int32_t       mOrder;                 // [reset] integer
1833   float         mFlexGrow;              // [reset] float
1834   float         mFlexShrink;            // [reset] float
1835   nsStyleCoord  mZIndex;                // [reset] integer, auto
1836   nsStyleGridTemplate mGridTemplateColumns;
1837   nsStyleGridTemplate mGridTemplateRows;
1838 
1839   // nullptr for 'none'
1840   RefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
1841 
1842   nsStyleGridLine mGridColumnStart;
1843   nsStyleGridLine mGridColumnEnd;
1844   nsStyleGridLine mGridRowStart;
1845   nsStyleGridLine mGridRowEnd;
1846   nsStyleCoord    mGridColumnGap;       // [reset] coord, percent, calc
1847   nsStyleCoord    mGridRowGap;          // [reset] coord, percent, calc
1848 
1849   // FIXME: Logical-coordinate equivalents to these WidthDepends... and
1850   // HeightDepends... methods have been introduced (see below); we probably
1851   // want to work towards removing the physical methods, and using the logical
1852   // ones in all cases.
1853 
WidthDependsOnContainernsStylePosition1854   bool WidthDependsOnContainer() const
1855     {
1856       return mWidth.GetUnit() == eStyleUnit_Auto ||
1857         WidthCoordDependsOnContainer(mWidth);
1858     }
1859 
1860   // NOTE: For a flex item, "min-width:auto" is supposed to behave like
1861   // "min-content", which does depend on the container, so you might think we'd
1862   // need a special case for "flex item && min-width:auto" here.  However,
1863   // we don't actually need that special-case code, because flex items are
1864   // explicitly supposed to *ignore* their min-width (i.e. behave like it's 0)
1865   // until the flex container explicitly considers it.  So -- since the flex
1866   // container doesn't rely on this method, we don't need to worry about
1867   // special behavior for flex items' "min-width:auto" values here.
MinWidthDependsOnContainernsStylePosition1868   bool MinWidthDependsOnContainer() const
1869     { return WidthCoordDependsOnContainer(mMinWidth); }
MaxWidthDependsOnContainernsStylePosition1870   bool MaxWidthDependsOnContainer() const
1871     { return WidthCoordDependsOnContainer(mMaxWidth); }
1872 
1873   // Note that these functions count 'auto' as depending on the
1874   // container since that's the case for absolutely positioned elements.
1875   // However, some callers do not care about this case and should check
1876   // for it, since it is the most common case.
1877   // FIXME: We should probably change the assumption to be the other way
1878   // around.
1879   // Consider this as part of moving to the logical-coordinate APIs.
HeightDependsOnContainernsStylePosition1880   bool HeightDependsOnContainer() const
1881     {
1882       return mHeight.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
1883         HeightCoordDependsOnContainer(mHeight);
1884     }
1885 
1886   // NOTE: The comment above MinWidthDependsOnContainer about flex items
1887   // applies here, too.
MinHeightDependsOnContainernsStylePosition1888   bool MinHeightDependsOnContainer() const
1889     { return HeightCoordDependsOnContainer(mMinHeight); }
MaxHeightDependsOnContainernsStylePosition1890   bool MaxHeightDependsOnContainer() const
1891     { return HeightCoordDependsOnContainer(mMaxHeight); }
1892 
OffsetHasPercentnsStylePosition1893   bool OffsetHasPercent(mozilla::css::Side aSide) const
1894   {
1895     return mOffset.Get(aSide).HasPercent();
1896   }
1897 
1898   // Logical-coordinate accessors for width and height properties,
1899   // given a WritingMode value. The definitions of these methods are
1900   // found in WritingModes.h (after the WritingMode class is fully
1901   // declared).
1902   inline nsStyleCoord& ISize(mozilla::WritingMode aWM);
1903   inline nsStyleCoord& MinISize(mozilla::WritingMode aWM);
1904   inline nsStyleCoord& MaxISize(mozilla::WritingMode aWM);
1905   inline nsStyleCoord& BSize(mozilla::WritingMode aWM);
1906   inline nsStyleCoord& MinBSize(mozilla::WritingMode aWM);
1907   inline nsStyleCoord& MaxBSize(mozilla::WritingMode aWM);
1908   inline const nsStyleCoord& ISize(mozilla::WritingMode aWM) const;
1909   inline const nsStyleCoord& MinISize(mozilla::WritingMode aWM) const;
1910   inline const nsStyleCoord& MaxISize(mozilla::WritingMode aWM) const;
1911   inline const nsStyleCoord& BSize(mozilla::WritingMode aWM) const;
1912   inline const nsStyleCoord& MinBSize(mozilla::WritingMode aWM) const;
1913   inline const nsStyleCoord& MaxBSize(mozilla::WritingMode aWM) const;
1914   inline bool ISizeDependsOnContainer(mozilla::WritingMode aWM) const;
1915   inline bool MinISizeDependsOnContainer(mozilla::WritingMode aWM) const;
1916   inline bool MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const;
1917   inline bool BSizeDependsOnContainer(mozilla::WritingMode aWM) const;
1918   inline bool MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
1919   inline bool MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
1920 
1921 private:
1922   static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
HeightCoordDependsOnContainernsStylePosition1923   static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
1924     { return aCoord.HasPercent(); }
1925 };
1926 
1927 struct nsStyleTextOverflowSide
1928 {
nsStyleTextOverflowSidensStyleTextOverflowSide1929   nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
1930 
1931   bool operator==(const nsStyleTextOverflowSide& aOther) const {
1932     return mType == aOther.mType &&
1933            (mType != NS_STYLE_TEXT_OVERFLOW_STRING ||
1934             mString == aOther.mString);
1935   }
1936   bool operator!=(const nsStyleTextOverflowSide& aOther) const {
1937     return !(*this == aOther);
1938   }
1939 
1940   nsString mString;
1941   uint8_t  mType;
1942 };
1943 
1944 struct nsStyleTextOverflow
1945 {
nsStyleTextOverflownsStyleTextOverflow1946   nsStyleTextOverflow() : mLogicalDirections(true) {}
1947   bool operator==(const nsStyleTextOverflow& aOther) const {
1948     return mLeft == aOther.mLeft && mRight == aOther.mRight;
1949   }
1950   bool operator!=(const nsStyleTextOverflow& aOther) const {
1951     return !(*this == aOther);
1952   }
1953 
1954   // Returns the value to apply on the left side.
GetLeftnsStyleTextOverflow1955   const nsStyleTextOverflowSide& GetLeft(uint8_t aDirection) const {
1956     NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
1957                  aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
1958     return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
1959              mLeft : mRight;
1960   }
1961 
1962   // Returns the value to apply on the right side.
GetRightnsStyleTextOverflow1963   const nsStyleTextOverflowSide& GetRight(uint8_t aDirection) const {
1964     NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
1965                  aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
1966     return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
1967              mRight : mLeft;
1968   }
1969 
1970   // Returns the first value that was specified.
GetFirstValuensStyleTextOverflow1971   const nsStyleTextOverflowSide* GetFirstValue() const {
1972     return mLogicalDirections ? &mRight : &mLeft;
1973   }
1974 
1975   // Returns the second value, or null if there was only one value specified.
GetSecondValuensStyleTextOverflow1976   const nsStyleTextOverflowSide* GetSecondValue() const {
1977     return mLogicalDirections ? nullptr : &mRight;
1978   }
1979 
1980   nsStyleTextOverflowSide mLeft;  // start side when mLogicalDirections is true
1981   nsStyleTextOverflowSide mRight; // end side when mLogicalDirections is true
1982   bool mLogicalDirections;  // true when only one value was specified
1983 };
1984 
1985 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset
1986 {
1987   explicit nsStyleTextReset(StyleStructContext aContext);
1988   nsStyleTextReset(const nsStyleTextReset& aOther);
1989   ~nsStyleTextReset();
FinishStylensStyleTextReset1990   void FinishStyle(nsPresContext* aPresContext) {}
1991 
newnsStyleTextReset1992   void* operator new(size_t sz, nsStyleTextReset* aSelf) { return aSelf; }
newnsStyleTextReset1993   void* operator new(size_t sz, nsPresContext* aContext) {
1994     return aContext->PresShell()->
1995       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, sz);
1996   }
DestroynsStyleTextReset1997   void Destroy(nsPresContext* aContext) {
1998     this->~nsStyleTextReset();
1999     aContext->PresShell()->
2000       FreeByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, this);
2001   }
2002 
2003   // Note the difference between this and
2004   // nsStyleContext::HasTextDecorationLines.
HasTextDecorationLinesnsStyleTextReset2005   bool HasTextDecorationLines() const {
2006     return mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_NONE &&
2007            mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
2008   }
2009 
2010   nsChangeHint CalcDifference(const nsStyleTextReset& aNewData) const;
MaxDifferencensStyleTextReset2011   static nsChangeHint MaxDifference() {
2012     return nsChangeHint(
2013         NS_STYLE_HINT_REFLOW |
2014         nsChangeHint_UpdateSubtreeOverflow);
2015   }
DifferenceAlwaysHandledForDescendantsnsStyleTextReset2016   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2017     // CalcDifference never returns the reflow hints that are sometimes
2018     // handled for descendants as hints not handled for descendants.
2019     return nsChangeHint_NeedReflow |
2020            nsChangeHint_ReflowChangesSizeOrPosition |
2021            nsChangeHint_ClearAncestorIntrinsics;
2022   }
2023 
2024   nsStyleTextOverflow mTextOverflow;    // [reset] enum, string
2025 
2026   uint8_t mTextDecorationLine;          // [reset] see nsStyleConsts.h
2027   uint8_t mTextDecorationStyle;         // [reset] see nsStyleConsts.h
2028   uint8_t mUnicodeBidi;                 // [reset] see nsStyleConsts.h
2029   nscoord mInitialLetterSink;           // [reset] 0 means normal
2030   float mInitialLetterSize;             // [reset] 0.0f means normal
2031   mozilla::StyleComplexColor mTextDecorationColor; // [reset]
2032 };
2033 
2034 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
2035 {
2036   explicit nsStyleText(StyleStructContext aContext);
2037   nsStyleText(const nsStyleText& aOther);
2038   ~nsStyleText();
FinishStylensStyleText2039   void FinishStyle(nsPresContext* aPresContext) {}
2040 
newnsStyleText2041   void* operator new(size_t sz, nsStyleText* aSelf) { return aSelf; }
newnsStyleText2042   void* operator new(size_t sz, nsPresContext* aContext) {
2043     return aContext->PresShell()->
2044       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz);
2045   }
DestroynsStyleText2046   void Destroy(nsPresContext* aContext) {
2047     this->~nsStyleText();
2048     aContext->PresShell()->
2049       FreeByObjectID(mozilla::eArenaObjectID_nsStyleText, this);
2050   }
2051 
2052   nsChangeHint CalcDifference(const nsStyleText& aNewData) const;
MaxDifferencensStyleText2053   static nsChangeHint MaxDifference() {
2054     return nsChangeHint_ReconstructFrame |
2055            NS_STYLE_HINT_REFLOW |
2056            nsChangeHint_UpdateSubtreeOverflow |
2057            nsChangeHint_NeutralChange;
2058   }
DifferenceAlwaysHandledForDescendantsnsStyleText2059   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2060     // CalcDifference never returns the reflow hints that are sometimes
2061     // handled for descendants as hints not handled for descendants.
2062     return nsChangeHint_NeedReflow |
2063            nsChangeHint_ReflowChangesSizeOrPosition |
2064            nsChangeHint_ClearAncestorIntrinsics;
2065   }
2066 
2067   uint8_t mTextAlign;                   // [inherited] see nsStyleConsts.h
2068   uint8_t mTextAlignLast;               // [inherited] see nsStyleConsts.h
2069   bool mTextAlignTrue : 1;              // [inherited] see nsStyleConsts.h
2070   bool mTextAlignLastTrue : 1;          // [inherited] see nsStyleConsts.h
2071   uint8_t mTextTransform;               // [inherited] see nsStyleConsts.h
2072   uint8_t mWhiteSpace;                  // [inherited] see nsStyleConsts.h
2073   uint8_t mWordBreak;                   // [inherited] see nsStyleConsts.h
2074   uint8_t mOverflowWrap;                // [inherited] see nsStyleConsts.h
2075   uint8_t mHyphens;                     // [inherited] see nsStyleConsts.h
2076   uint8_t mRubyAlign;                   // [inherited] see nsStyleConsts.h
2077   uint8_t mRubyPosition;                // [inherited] see nsStyleConsts.h
2078   uint8_t mTextSizeAdjust;              // [inherited] see nsStyleConsts.h
2079   uint8_t mTextCombineUpright;          // [inherited] see nsStyleConsts.h
2080   uint8_t mControlCharacterVisibility;  // [inherited] see nsStyleConsts.h
2081   uint8_t mTextEmphasisPosition;        // [inherited] see nsStyleConsts.h
2082   uint8_t mTextEmphasisStyle;           // [inherited] see nsStyleConsts.h
2083   uint8_t mTextRendering;               // [inherited] see nsStyleConsts.h
2084   int32_t mTabSize;                     // [inherited] see nsStyleConsts.h
2085   mozilla::StyleComplexColor mTextEmphasisColor;      // [inherited]
2086   mozilla::StyleComplexColor mWebkitTextFillColor;    // [inherited]
2087   mozilla::StyleComplexColor mWebkitTextStrokeColor;  // [inherited]
2088 
2089   nsStyleCoord mWordSpacing;            // [inherited] coord, percent, calc
2090   nsStyleCoord mLetterSpacing;          // [inherited] coord, normal
2091   nsStyleCoord mLineHeight;             // [inherited] coord, factor, normal
2092   nsStyleCoord mTextIndent;             // [inherited] coord, percent, calc
2093   nsStyleCoord mWebkitTextStrokeWidth;  // [inherited] coord
2094 
2095   RefPtr<nsCSSShadowArray> mTextShadow; // [inherited] nullptr in case of a zero-length
2096 
2097   nsString mTextEmphasisStyleString;    // [inherited]
2098 
WhiteSpaceIsSignificantnsStyleText2099   bool WhiteSpaceIsSignificant() const {
2100     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2101            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2102            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
2103   }
2104 
NewlineIsSignificantStylensStyleText2105   bool NewlineIsSignificantStyle() const {
2106     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2107            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2108            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
2109   }
2110 
WhiteSpaceOrNewlineIsSignificantnsStyleText2111   bool WhiteSpaceOrNewlineIsSignificant() const {
2112     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2113            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2114            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
2115            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
2116   }
2117 
TabIsSignificantnsStyleText2118   bool TabIsSignificant() const {
2119     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2120            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
2121   }
2122 
WhiteSpaceCanWrapStylensStyleText2123   bool WhiteSpaceCanWrapStyle() const {
2124     return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
2125            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2126            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
2127   }
2128 
WordCanWrapStylensStyleText2129   bool WordCanWrapStyle() const {
2130     return WhiteSpaceCanWrapStyle() &&
2131            mOverflowWrap == NS_STYLE_OVERFLOWWRAP_BREAK_WORD;
2132   }
2133 
HasTextEmphasisnsStyleText2134   bool HasTextEmphasis() const {
2135     return !mTextEmphasisStyleString.IsEmpty();
2136   }
2137 
HasWebkitTextStrokensStyleText2138   bool HasWebkitTextStroke() const {
2139     return mWebkitTextStrokeWidth.GetCoordValue() > 0;
2140   }
2141 
2142   // These are defined in nsStyleStructInlines.h.
2143   inline bool HasTextShadow() const;
2144   inline nsCSSShadowArray* GetTextShadow() const;
2145 
2146   // The aContextFrame argument on each of these is the frame this
2147   // style struct is for.  If the frame is for SVG text or inside ruby,
2148   // the return value will be massaged to be something that makes sense
2149   // for those cases.
2150   inline bool NewlineIsSignificant(const nsTextFrame* aContextFrame) const;
2151   inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
2152   inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
2153 
2154   mozilla::LogicalSide TextEmphasisSide(mozilla::WritingMode aWM) const;
2155 };
2156 
2157 struct nsStyleImageOrientation
2158 {
CreateAsAngleAndFlipnsStyleImageOrientation2159   static nsStyleImageOrientation CreateAsAngleAndFlip(double aRadians,
2160                                                       bool aFlip) {
2161     uint8_t orientation(0);
2162 
2163     // Compute the final angle value, rounding to the closest quarter turn.
2164     double roundedAngle = fmod(aRadians, 2 * M_PI);
2165     if      (roundedAngle < 0.25 * M_PI) { orientation = ANGLE_0;  }
2166     else if (roundedAngle < 0.75 * M_PI) { orientation = ANGLE_90; }
2167     else if (roundedAngle < 1.25 * M_PI) { orientation = ANGLE_180;}
2168     else if (roundedAngle < 1.75 * M_PI) { orientation = ANGLE_270;}
2169     else                                 { orientation = ANGLE_0;  }
2170 
2171     // Add a bit for 'flip' if needed.
2172     if (aFlip) {
2173       orientation |= FLIP_MASK;
2174     }
2175 
2176     return nsStyleImageOrientation(orientation);
2177   }
2178 
CreateAsFlipnsStyleImageOrientation2179   static nsStyleImageOrientation CreateAsFlip() {
2180     return nsStyleImageOrientation(FLIP_MASK);
2181   }
2182 
CreateAsFromImagensStyleImageOrientation2183   static nsStyleImageOrientation CreateAsFromImage() {
2184     return nsStyleImageOrientation(FROM_IMAGE_MASK);
2185   }
2186 
2187   // The default constructor yields 0 degrees of rotation and no flip.
nsStyleImageOrientationnsStyleImageOrientation2188   nsStyleImageOrientation() : mOrientation(0) { }
2189 
IsDefaultnsStyleImageOrientation2190   bool IsDefault()   const { return mOrientation == 0; }
IsFlippednsStyleImageOrientation2191   bool IsFlipped()   const { return mOrientation & FLIP_MASK; }
IsFromImagensStyleImageOrientation2192   bool IsFromImage() const { return mOrientation & FROM_IMAGE_MASK; }
SwapsWidthAndHeightnsStyleImageOrientation2193   bool SwapsWidthAndHeight() const {
2194     uint8_t angle = mOrientation & ORIENTATION_MASK;
2195     return (angle == ANGLE_90) || (angle == ANGLE_270);
2196   }
2197 
AnglensStyleImageOrientation2198   mozilla::image::Angle Angle() const {
2199     switch (mOrientation & ORIENTATION_MASK) {
2200       case ANGLE_0:   return mozilla::image::Angle::D0;
2201       case ANGLE_90:  return mozilla::image::Angle::D90;
2202       case ANGLE_180: return mozilla::image::Angle::D180;
2203       case ANGLE_270: return mozilla::image::Angle::D270;
2204       default:
2205         NS_NOTREACHED("Unexpected angle");
2206         return mozilla::image::Angle::D0;
2207     }
2208   }
2209 
AngleAsCoordnsStyleImageOrientation2210   nsStyleCoord AngleAsCoord() const {
2211     switch (mOrientation & ORIENTATION_MASK) {
2212       case ANGLE_0:   return nsStyleCoord(0.0f,   eStyleUnit_Degree);
2213       case ANGLE_90:  return nsStyleCoord(90.0f,  eStyleUnit_Degree);
2214       case ANGLE_180: return nsStyleCoord(180.0f, eStyleUnit_Degree);
2215       case ANGLE_270: return nsStyleCoord(270.0f, eStyleUnit_Degree);
2216       default:
2217         NS_NOTREACHED("Unexpected angle");
2218         return nsStyleCoord();
2219     }
2220   }
2221 
2222   bool operator==(const nsStyleImageOrientation& aOther) const {
2223     return aOther.mOrientation == mOrientation;
2224   }
2225 
2226   bool operator!=(const nsStyleImageOrientation& aOther) const {
2227     return !(*this == aOther);
2228   }
2229 
2230 protected:
2231   enum Bits {
2232     ORIENTATION_MASK = 0x1 | 0x2,  // The bottom two bits are the angle.
2233     FLIP_MASK        = 0x4,        // Whether the image should be flipped.
2234     FROM_IMAGE_MASK  = 0x8,        // Whether the image's inherent orientation
2235   };                               // should be used.
2236 
2237   enum Angles {
2238     ANGLE_0   = 0,
2239     ANGLE_90  = 1,
2240     ANGLE_180 = 2,
2241     ANGLE_270 = 3,
2242   };
2243 
nsStyleImageOrientationnsStyleImageOrientation2244   explicit nsStyleImageOrientation(uint8_t aOrientation)
2245     : mOrientation(aOrientation)
2246   { }
2247 
2248   uint8_t mOrientation;
2249 };
2250 
2251 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility
2252 {
2253   explicit nsStyleVisibility(StyleStructContext aContext);
2254   nsStyleVisibility(const nsStyleVisibility& aVisibility);
~nsStyleVisibilitynsStyleVisibility2255   ~nsStyleVisibility() {
2256     MOZ_COUNT_DTOR(nsStyleVisibility);
2257   }
FinishStylensStyleVisibility2258   void FinishStyle(nsPresContext* aPresContext) {}
2259 
newnsStyleVisibility2260   void* operator new(size_t sz, nsStyleVisibility* aSelf) { return aSelf; }
newnsStyleVisibility2261   void* operator new(size_t sz, nsPresContext* aContext) {
2262     return aContext->PresShell()->
2263       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz);
2264   }
DestroynsStyleVisibility2265   void Destroy(nsPresContext* aContext) {
2266     this->~nsStyleVisibility();
2267     aContext->PresShell()->
2268       FreeByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, this);
2269   }
2270 
2271   nsChangeHint CalcDifference(const nsStyleVisibility& aNewData) const;
MaxDifferencensStyleVisibility2272   static nsChangeHint MaxDifference() {
2273     return nsChangeHint_ReconstructFrame |
2274            NS_STYLE_HINT_REFLOW |
2275            nsChangeHint_NeutralChange;
2276   }
DifferenceAlwaysHandledForDescendantsnsStyleVisibility2277   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2278     // CalcDifference never returns the reflow hints that are sometimes
2279     // handled for descendants as hints not handled for descendants.
2280     return nsChangeHint_NeedReflow |
2281            nsChangeHint_ReflowChangesSizeOrPosition |
2282            nsChangeHint_ClearAncestorIntrinsics;
2283   }
2284 
2285   nsStyleImageOrientation mImageOrientation;  // [inherited]
2286   uint8_t mDirection;                  // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
2287   uint8_t mVisible;                    // [inherited]
2288   uint8_t mImageRendering;             // [inherited] see nsStyleConsts.h
2289   uint8_t mWritingMode;                // [inherited] see nsStyleConsts.h
2290   uint8_t mTextOrientation;            // [inherited] see nsStyleConsts.h
2291   uint8_t mColorAdjust;                // [inherited] see nsStyleConsts.h
2292 
IsVisiblensStyleVisibility2293   bool IsVisible() const {
2294     return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
2295   }
2296 
IsVisibleOrCollapsednsStyleVisibility2297   bool IsVisibleOrCollapsed() const {
2298     return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
2299             (mVisible == NS_STYLE_VISIBILITY_COLLAPSE));
2300   }
2301 };
2302 
2303 struct nsTimingFunction
2304 {
2305 
2306   enum class Type {
2307     Ease,         // ease
2308     Linear,       // linear
2309     EaseIn,       // ease-in
2310     EaseOut,      // ease-out
2311     EaseInOut,    // ease-in-out
2312     StepStart,    // step-start and steps(..., start)
2313     StepEnd,      // step-end, steps(..., end) and steps(...)
2314     CubicBezier,  // cubic-bezier()
2315   };
2316 
2317   // Whether the timing function type is represented by a spline,
2318   // and thus will have mFunc filled in.
IsSplineTypensTimingFunction2319   static bool IsSplineType(Type aType)
2320   {
2321     return aType != Type::StepStart && aType != Type::StepEnd;
2322   }
2323 
2324   explicit nsTimingFunction(int32_t aTimingFunctionType
2325                               = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)
2326   {
2327     AssignFromKeyword(aTimingFunctionType);
2328   }
2329 
nsTimingFunctionnsTimingFunction2330   nsTimingFunction(float x1, float y1, float x2, float y2)
2331     : mType(Type::CubicBezier)
2332   {
2333     mFunc.mX1 = x1;
2334     mFunc.mY1 = y1;
2335     mFunc.mX2 = x2;
2336     mFunc.mY2 = y2;
2337   }
2338 
2339   enum class Keyword { Implicit, Explicit };
2340 
nsTimingFunctionnsTimingFunction2341   nsTimingFunction(Type aType, uint32_t aSteps)
2342     : mType(aType)
2343   {
2344     MOZ_ASSERT(mType == Type::StepStart || mType == Type::StepEnd,
2345                "wrong type");
2346     mSteps = aSteps;
2347   }
2348 
nsTimingFunctionnsTimingFunction2349   nsTimingFunction(const nsTimingFunction& aOther)
2350   {
2351     *this = aOther;
2352   }
2353 
2354   Type mType;
2355   union {
2356     struct {
2357       float mX1;
2358       float mY1;
2359       float mX2;
2360       float mY2;
2361     } mFunc;
2362     struct {
2363       uint32_t mSteps;
2364     };
2365   };
2366 
2367   nsTimingFunction&
2368   operator=(const nsTimingFunction& aOther)
2369   {
2370     if (&aOther == this) {
2371       return *this;
2372     }
2373 
2374     mType = aOther.mType;
2375 
2376     if (HasSpline()) {
2377       mFunc.mX1 = aOther.mFunc.mX1;
2378       mFunc.mY1 = aOther.mFunc.mY1;
2379       mFunc.mX2 = aOther.mFunc.mX2;
2380       mFunc.mY2 = aOther.mFunc.mY2;
2381     } else {
2382       mSteps = aOther.mSteps;
2383     }
2384 
2385     return *this;
2386   }
2387 
2388   bool operator==(const nsTimingFunction& aOther) const
2389   {
2390     if (mType != aOther.mType) {
2391       return false;
2392     }
2393     if (HasSpline()) {
2394       return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
2395              mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
2396     }
2397     return mSteps == aOther.mSteps;
2398   }
2399 
2400   bool operator!=(const nsTimingFunction& aOther) const
2401   {
2402     return !(*this == aOther);
2403   }
2404 
HasSplinensTimingFunction2405   bool HasSpline() const { return IsSplineType(mType); }
2406 
2407 private:
2408   void AssignFromKeyword(int32_t aTimingFunctionType);
2409 };
2410 
2411 namespace mozilla {
2412 
2413 struct StyleTransition
2414 {
StyleTransitionStyleTransition2415   StyleTransition() { /* leaves uninitialized; see also SetInitialValues */ }
2416   explicit StyleTransition(const StyleTransition& aCopy);
2417 
2418   void SetInitialValues();
2419 
2420   // Delay and Duration are in milliseconds
2421 
GetTimingFunctionStyleTransition2422   const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
GetDelayStyleTransition2423   float GetDelay() const { return mDelay; }
GetDurationStyleTransition2424   float GetDuration() const { return mDuration; }
GetPropertyStyleTransition2425   nsCSSPropertyID GetProperty() const { return mProperty; }
GetUnknownPropertyStyleTransition2426   nsIAtom* GetUnknownProperty() const { return mUnknownProperty; }
2427 
GetCombinedDurationStyleTransition2428   float GetCombinedDuration() const {
2429     // http://dev.w3.org/csswg/css-transitions/#combined-duration
2430     return std::max(mDuration, 0.0f) + mDelay;
2431   }
2432 
SetTimingFunctionStyleTransition2433   void SetTimingFunction(const nsTimingFunction& aTimingFunction)
2434     { mTimingFunction = aTimingFunction; }
SetDelayStyleTransition2435   void SetDelay(float aDelay) { mDelay = aDelay; }
SetDurationStyleTransition2436   void SetDuration(float aDuration) { mDuration = aDuration; }
SetPropertyStyleTransition2437   void SetProperty(nsCSSPropertyID aProperty)
2438     {
2439       NS_ASSERTION(aProperty != eCSSProperty_UNKNOWN &&
2440                    aProperty != eCSSPropertyExtra_variable,
2441                    "invalid property");
2442       mProperty = aProperty;
2443     }
2444   void SetUnknownProperty(nsCSSPropertyID aProperty,
2445                           const nsAString& aPropertyString);
CopyPropertyFromStyleTransition2446   void CopyPropertyFrom(const StyleTransition& aOther)
2447     {
2448       mProperty = aOther.mProperty;
2449       mUnknownProperty = aOther.mUnknownProperty;
2450     }
2451 
TimingFunctionSlotStyleTransition2452   nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
2453 
2454   bool operator==(const StyleTransition& aOther) const;
2455   bool operator!=(const StyleTransition& aOther) const
2456     { return !(*this == aOther); }
2457 
2458 private:
2459   nsTimingFunction mTimingFunction;
2460   float mDuration;
2461   float mDelay;
2462   nsCSSPropertyID mProperty;
2463   nsCOMPtr<nsIAtom> mUnknownProperty; // used when mProperty is
2464                                       // eCSSProperty_UNKNOWN or
2465                                       // eCSSPropertyExtra_variable
2466 };
2467 
2468 struct StyleAnimation
2469 {
StyleAnimationStyleAnimation2470   StyleAnimation() { /* leaves uninitialized; see also SetInitialValues */ }
2471   explicit StyleAnimation(const StyleAnimation& aCopy);
2472 
2473   void SetInitialValues();
2474 
2475   // Delay and Duration are in milliseconds
2476 
GetTimingFunctionStyleAnimation2477   const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
GetDelayStyleAnimation2478   float GetDelay() const { return mDelay; }
GetDurationStyleAnimation2479   float GetDuration() const { return mDuration; }
GetNameStyleAnimation2480   const nsString& GetName() const { return mName; }
GetDirectionStyleAnimation2481   dom::PlaybackDirection GetDirection() const { return mDirection; }
GetFillModeStyleAnimation2482   dom::FillMode GetFillMode() const { return mFillMode; }
GetPlayStateStyleAnimation2483   uint8_t GetPlayState() const { return mPlayState; }
GetIterationCountStyleAnimation2484   float GetIterationCount() const { return mIterationCount; }
2485 
SetTimingFunctionStyleAnimation2486   void SetTimingFunction(const nsTimingFunction& aTimingFunction)
2487     { mTimingFunction = aTimingFunction; }
SetDelayStyleAnimation2488   void SetDelay(float aDelay) { mDelay = aDelay; }
SetDurationStyleAnimation2489   void SetDuration(float aDuration) { mDuration = aDuration; }
SetNameStyleAnimation2490   void SetName(const nsSubstring& aName) { mName = aName; }
SetDirectionStyleAnimation2491   void SetDirection(dom::PlaybackDirection aDirection) { mDirection = aDirection; }
SetFillModeStyleAnimation2492   void SetFillMode(dom::FillMode aFillMode) { mFillMode = aFillMode; }
SetPlayStateStyleAnimation2493   void SetPlayState(uint8_t aPlayState) { mPlayState = aPlayState; }
SetIterationCountStyleAnimation2494   void SetIterationCount(float aIterationCount)
2495     { mIterationCount = aIterationCount; }
2496 
TimingFunctionSlotStyleAnimation2497   nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
2498 
2499   bool operator==(const StyleAnimation& aOther) const;
2500   bool operator!=(const StyleAnimation& aOther) const
2501     { return !(*this == aOther); }
2502 
2503 private:
2504   nsTimingFunction mTimingFunction;
2505   float mDuration;
2506   float mDelay;
2507   nsString mName; // empty string for 'none'
2508   dom::PlaybackDirection mDirection;
2509   dom::FillMode mFillMode;
2510   uint8_t mPlayState;
2511   float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
2512 };
2513 
2514 class StyleBasicShape final
2515 {
2516 public:
StyleBasicShape(StyleBasicShapeType type)2517   explicit StyleBasicShape(StyleBasicShapeType type)
2518     : mType(type),
2519       mFillRule(StyleFillRule::Nonzero)
2520   {
2521     mPosition.SetInitialPercentValues(0.5f);
2522   }
2523 
GetShapeType()2524   StyleBasicShapeType GetShapeType() const { return mType; }
2525   nsCSSKeyword GetShapeTypeName() const;
2526 
GetFillRule()2527   StyleFillRule GetFillRule() const { return mFillRule; }
SetFillRule(StyleFillRule aFillRule)2528   void SetFillRule(StyleFillRule aFillRule)
2529   {
2530     MOZ_ASSERT(mType == StyleBasicShapeType::Polygon, "expected polygon");
2531     mFillRule = aFillRule;
2532   }
2533 
GetPosition()2534   Position& GetPosition() {
2535     MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
2536                mType == StyleBasicShapeType::Ellipse,
2537                "expected circle or ellipse");
2538     return mPosition;
2539   }
GetPosition()2540   const Position& GetPosition() const {
2541     MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
2542                mType == StyleBasicShapeType::Ellipse,
2543                "expected circle or ellipse");
2544     return mPosition;
2545   }
2546 
HasRadius()2547   bool HasRadius() const {
2548     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
2549     nsStyleCoord zero;
2550     zero.SetCoordValue(0);
2551     NS_FOR_CSS_HALF_CORNERS(corner) {
2552       if (mRadius.Get(corner) != zero) {
2553         return true;
2554       }
2555     }
2556     return false;
2557   }
GetRadius()2558   nsStyleCorners& GetRadius() {
2559     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
2560     return mRadius;
2561   }
GetRadius()2562   const nsStyleCorners& GetRadius() const {
2563     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
2564     return mRadius;
2565   }
2566 
2567   // mCoordinates has coordinates for polygon or radii for
2568   // ellipse and circle.
Coordinates()2569   nsTArray<nsStyleCoord>& Coordinates()
2570   {
2571     return mCoordinates;
2572   }
2573 
Coordinates()2574   const nsTArray<nsStyleCoord>& Coordinates() const
2575   {
2576     return mCoordinates;
2577   }
2578 
2579   bool operator==(const StyleBasicShape& aOther) const
2580   {
2581     return mType == aOther.mType &&
2582            mFillRule == aOther.mFillRule &&
2583            mCoordinates == aOther.mCoordinates &&
2584            mPosition == aOther.mPosition &&
2585            mRadius == aOther.mRadius;
2586   }
2587   bool operator!=(const StyleBasicShape& aOther) const {
2588     return !(*this == aOther);
2589   }
2590 
2591   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StyleBasicShape);
2592 
2593 private:
~StyleBasicShape()2594   ~StyleBasicShape() {}
2595 
2596   StyleBasicShapeType mType;
2597   StyleFillRule mFillRule;
2598 
2599   // mCoordinates has coordinates for polygon or radii for
2600   // ellipse and circle.
2601   // (top, right, bottom, left) for inset
2602   nsTArray<nsStyleCoord> mCoordinates;
2603   // position of center for ellipse or circle
2604   Position mPosition;
2605   // corner radii for inset (0 if not set)
2606   nsStyleCorners mRadius;
2607 };
2608 
2609 template<typename ReferenceBox>
2610 struct StyleShapeSource
2611 {
StyleShapeSourceStyleShapeSource2612   StyleShapeSource()
2613     : mURL(nullptr)
2614   {}
2615 
StyleShapeSourceStyleShapeSource2616   StyleShapeSource(const StyleShapeSource& aSource)
2617     : StyleShapeSource()
2618   {
2619     if (aSource.mType == StyleShapeSourceType::URL) {
2620       SetURL(aSource.mURL);
2621     } else if (aSource.mType == StyleShapeSourceType::Shape) {
2622       SetBasicShape(aSource.mBasicShape, aSource.mReferenceBox);
2623     } else if (aSource.mType == StyleShapeSourceType::Box) {
2624       SetReferenceBox(aSource.mReferenceBox);
2625     }
2626   }
2627 
~StyleShapeSourceStyleShapeSource2628   ~StyleShapeSource()
2629   {
2630     ReleaseRef();
2631   }
2632 
2633   StyleShapeSource& operator=(const StyleShapeSource& aOther)
2634   {
2635     if (this == &aOther) {
2636       return *this;
2637     }
2638 
2639     if (aOther.mType == StyleShapeSourceType::URL) {
2640       SetURL(aOther.mURL);
2641     } else if (aOther.mType == StyleShapeSourceType::Shape) {
2642       SetBasicShape(aOther.mBasicShape, aOther.mReferenceBox);
2643     } else if (aOther.mType == StyleShapeSourceType::Box) {
2644       SetReferenceBox(aOther.mReferenceBox);
2645     } else {
2646       ReleaseRef();
2647       mReferenceBox = ReferenceBox::NoBox;
2648       mType = StyleShapeSourceType::None;
2649     }
2650     return *this;
2651   }
2652 
2653   bool operator==(const StyleShapeSource& aOther) const
2654   {
2655     if (mType != aOther.mType) {
2656       return false;
2657     }
2658 
2659     if (mType == StyleShapeSourceType::URL) {
2660       return mURL->Equals(*aOther.mURL);
2661     } else if (mType == StyleShapeSourceType::Shape) {
2662       return *mBasicShape == *aOther.mBasicShape &&
2663              mReferenceBox == aOther.mReferenceBox;
2664     } else if (mType == StyleShapeSourceType::Box) {
2665       return mReferenceBox == aOther.mReferenceBox;
2666     }
2667 
2668     return true;
2669   }
2670 
2671   bool operator!=(const StyleShapeSource& aOther) const
2672   {
2673     return !(*this == aOther);
2674   }
2675 
GetTypeStyleShapeSource2676   StyleShapeSourceType GetType() const
2677   {
2678     return mType;
2679   }
2680 
GetURLStyleShapeSource2681   css::URLValue* GetURL() const
2682   {
2683     MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
2684     return mURL;
2685   }
2686 
SetURLStyleShapeSource2687   bool SetURL(css::URLValue* aValue)
2688   {
2689     MOZ_ASSERT(aValue);
2690     ReleaseRef();
2691     mURL = aValue;
2692     mURL->AddRef();
2693     mType = StyleShapeSourceType::URL;
2694     return true;
2695   }
2696 
GetBasicShapeStyleShapeSource2697   StyleBasicShape* GetBasicShape() const
2698   {
2699     MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
2700     return mBasicShape;
2701   }
2702 
SetBasicShapeStyleShapeSource2703   void SetBasicShape(StyleBasicShape* aBasicShape,
2704                      ReferenceBox aReferenceBox)
2705   {
2706     NS_ASSERTION(aBasicShape, "expected pointer");
2707     ReleaseRef();
2708     mBasicShape = aBasicShape;
2709     mBasicShape->AddRef();
2710     mReferenceBox = aReferenceBox;
2711     mType = StyleShapeSourceType::Shape;
2712   }
2713 
GetReferenceBoxStyleShapeSource2714   ReferenceBox GetReferenceBox() const
2715   {
2716     MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
2717                mType == StyleShapeSourceType::Shape,
2718                "Wrong shape source type!");
2719     return mReferenceBox;
2720   }
2721 
SetReferenceBoxStyleShapeSource2722   void SetReferenceBox(ReferenceBox aReferenceBox)
2723   {
2724     ReleaseRef();
2725     mReferenceBox = aReferenceBox;
2726     mType = StyleShapeSourceType::Box;
2727   }
2728 
2729 private:
ReleaseRefStyleShapeSource2730   void ReleaseRef()
2731   {
2732     if (mType == StyleShapeSourceType::Shape) {
2733       NS_ASSERTION(mBasicShape, "expected pointer");
2734       mBasicShape->Release();
2735     } else if (mType == StyleShapeSourceType::URL) {
2736       NS_ASSERTION(mURL, "expected pointer");
2737       mURL->Release();
2738     }
2739     // Both mBasicShape and mURL are pointers in a union. Nulling one of them
2740     // nulls both of them.
2741     mURL = nullptr;
2742   }
2743 
2744   void* operator new(size_t) = delete;
2745 
2746   union {
2747     StyleBasicShape* mBasicShape;
2748     css::URLValue* mURL;
2749   };
2750   StyleShapeSourceType mType = StyleShapeSourceType::None;
2751   ReferenceBox mReferenceBox = ReferenceBox::NoBox;
2752 };
2753 
2754 using StyleClipPath = StyleShapeSource<StyleClipPathGeometryBox>;
2755 using StyleShapeOutside = StyleShapeSource<StyleShapeOutsideShapeBox>;
2756 
2757 } // namespace mozilla
2758 
2759 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
2760 {
2761   explicit nsStyleDisplay(StyleStructContext aContext);
2762   nsStyleDisplay(const nsStyleDisplay& aOther);
~nsStyleDisplaynsStyleDisplay2763   ~nsStyleDisplay() {
2764     MOZ_COUNT_DTOR(nsStyleDisplay);
2765   }
FinishStylensStyleDisplay2766   void FinishStyle(nsPresContext* aPresContext) {}
2767 
newnsStyleDisplay2768   void* operator new(size_t sz, nsStyleDisplay* aSelf) { return aSelf; }
newnsStyleDisplay2769   void* operator new(size_t sz, nsPresContext* aContext) {
2770     return aContext->PresShell()->
2771       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz);
2772   }
DestroynsStyleDisplay2773   void Destroy(nsPresContext* aContext) {
2774     this->~nsStyleDisplay();
2775     aContext->PresShell()->
2776       FreeByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, this);
2777   }
2778 
2779   nsChangeHint CalcDifference(const nsStyleDisplay& aNewData) const;
MaxDifferencensStyleDisplay2780   static nsChangeHint MaxDifference() {
2781     // All the parts of FRAMECHANGE are present in CalcDifference.
2782     return nsChangeHint(nsChangeHint_ReconstructFrame |
2783                         NS_STYLE_HINT_REFLOW |
2784                         nsChangeHint_UpdateTransformLayer |
2785                         nsChangeHint_UpdateOverflow |
2786                         nsChangeHint_UpdatePostTransformOverflow |
2787                         nsChangeHint_UpdateContainingBlock |
2788                         nsChangeHint_AddOrRemoveTransform |
2789                         nsChangeHint_NeutralChange);
2790   }
DifferenceAlwaysHandledForDescendantsnsStyleDisplay2791   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2792     // CalcDifference can return all of the reflow hints that are
2793     // sometimes handled for descendants as hints not handled for
2794     // descendants.
2795     return nsChangeHint(0);
2796   }
2797 
2798   // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
2799   // mBinding->mOriginPrincipal.
2800   RefPtr<mozilla::css::URLValue> mBinding; // [reset]
2801   mozilla::StyleDisplay mDisplay;          // [reset] see nsStyleConsts.h SyleDisplay
2802   mozilla::StyleDisplay mOriginalDisplay;  // [reset] saved mDisplay for
2803                                            //         position:absolute/fixed
2804                                            //         and float:left/right;
2805                                            //         otherwise equal to
2806                                            //         mDisplay
2807   uint8_t mContain;             // [reset] see nsStyleConsts.h NS_STYLE_CONTAIN_*
2808   uint8_t mAppearance;          // [reset]
2809   uint8_t mPosition;            // [reset] see nsStyleConsts.h
2810 
2811   // [reset] See StyleFloat in nsStyleConsts.h.
2812   mozilla::StyleFloat mFloat;
2813   // [reset] Save mFloat for position:absolute/fixed; otherwise equal to mFloat.
2814   mozilla::StyleFloat mOriginalFloat;
2815 
2816   mozilla::StyleClear mBreakType;  // [reset]
2817   uint8_t mBreakInside;         // [reset] NS_STYLE_PAGE_BREAK_AUTO/AVOID
2818   bool mBreakBefore;    // [reset]
2819   bool mBreakAfter;     // [reset]
2820   uint8_t mOverflowX;           // [reset] see nsStyleConsts.h
2821   uint8_t mOverflowY;           // [reset] see nsStyleConsts.h
2822   uint8_t mOverflowClipBox;     // [reset] see nsStyleConsts.h
2823   uint8_t mResize;              // [reset] see nsStyleConsts.h
2824   mozilla::StyleOrient mOrient; // [reset] see nsStyleConsts.h
2825   uint8_t mIsolation;           // [reset] see nsStyleConsts.h
2826   uint8_t mTopLayer;            // [reset] see nsStyleConsts.h
2827   uint8_t mWillChangeBitField;  // [reset] see nsStyleConsts.h. Stores a
2828                                 // bitfield representation of the properties
2829                                 // that are frequently queried. This should
2830                                 // match mWillChange. Also tracks if any of the
2831                                 // properties in the will-change list require
2832                                 // a stacking context.
2833   nsTArray<nsString> mWillChange;
2834 
2835   uint8_t mTouchAction;         // [reset] see nsStyleConsts.h
2836   uint8_t mScrollBehavior;      // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_BEHAVIOR_*
2837   uint8_t mScrollSnapTypeX;     // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_SNAP_TYPE_*
2838   uint8_t mScrollSnapTypeY;     // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_SNAP_TYPE_*
2839   nsStyleCoord mScrollSnapPointsX; // [reset]
2840   nsStyleCoord mScrollSnapPointsY; // [reset]
2841   mozilla::Position mScrollSnapDestination; // [reset]
2842   nsTArray<mozilla::Position> mScrollSnapCoordinate; // [reset]
2843 
2844   // mSpecifiedTransform is the list of transform functions as
2845   // specified, or null to indicate there is no transform.  (inherit or
2846   // initial are replaced by an actual list of transform functions, or
2847   // null, as appropriate.)
2848   uint8_t mBackfaceVisibility;
2849   uint8_t mTransformStyle;
2850   uint8_t mTransformBox;        // [reset] see nsStyleConsts.h
2851   RefPtr<nsCSSValueSharedList> mSpecifiedTransform; // [reset]
2852   nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
2853   nsStyleCoord mChildPerspective; // [reset] none, coord
2854   nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
2855 
2856   nsStyleCoord mVerticalAlign;  // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
2857 
2858   nsStyleAutoArray<mozilla::StyleTransition> mTransitions; // [reset]
2859 
2860   // The number of elements in mTransitions that are not from repeating
2861   // a list due to another property being longer.
2862   uint32_t mTransitionTimingFunctionCount,
2863            mTransitionDurationCount,
2864            mTransitionDelayCount,
2865            mTransitionPropertyCount;
2866 
2867   nsStyleAutoArray<mozilla::StyleAnimation> mAnimations; // [reset]
2868 
2869   // The number of elements in mAnimations that are not from repeating
2870   // a list due to another property being longer.
2871   uint32_t mAnimationTimingFunctionCount,
2872            mAnimationDurationCount,
2873            mAnimationDelayCount,
2874            mAnimationNameCount,
2875            mAnimationDirectionCount,
2876            mAnimationFillModeCount,
2877            mAnimationPlayStateCount,
2878            mAnimationIterationCountCount;
2879 
2880   mozilla::StyleShapeOutside mShapeOutside; // [reset]
2881 
IsBlockInsideStylensStyleDisplay2882   bool IsBlockInsideStyle() const {
2883     return mozilla::StyleDisplay::Block == mDisplay ||
2884            mozilla::StyleDisplay::ListItem == mDisplay ||
2885            mozilla::StyleDisplay::InlineBlock == mDisplay ||
2886            mozilla::StyleDisplay::TableCaption == mDisplay;
2887     // Should TABLE_CELL be included here?  They have
2888     // block frames nested inside of them.
2889     // (But please audit all callers before changing.)
2890   }
2891 
IsBlockOutsideStylensStyleDisplay2892   bool IsBlockOutsideStyle() const {
2893     return mozilla::StyleDisplay::Block == mDisplay ||
2894            mozilla::StyleDisplay::Flex == mDisplay ||
2895            mozilla::StyleDisplay::WebkitBox == mDisplay ||
2896            mozilla::StyleDisplay::Grid == mDisplay ||
2897            mozilla::StyleDisplay::ListItem == mDisplay ||
2898            mozilla::StyleDisplay::Table == mDisplay;
2899   }
2900 
IsDisplayTypeInlineOutsidensStyleDisplay2901   static bool IsDisplayTypeInlineOutside(mozilla::StyleDisplay aDisplay) {
2902     return mozilla::StyleDisplay::Inline == aDisplay ||
2903            mozilla::StyleDisplay::InlineBlock == aDisplay ||
2904            mozilla::StyleDisplay::InlineTable == aDisplay ||
2905            mozilla::StyleDisplay::InlineBox == aDisplay ||
2906            mozilla::StyleDisplay::InlineFlex == aDisplay ||
2907            mozilla::StyleDisplay::WebkitInlineBox == aDisplay ||
2908            mozilla::StyleDisplay::InlineGrid == aDisplay ||
2909            mozilla::StyleDisplay::InlineXulGrid == aDisplay ||
2910            mozilla::StyleDisplay::InlineStack == aDisplay ||
2911            mozilla::StyleDisplay::Ruby == aDisplay ||
2912            mozilla::StyleDisplay::RubyBase == aDisplay ||
2913            mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||
2914            mozilla::StyleDisplay::RubyText == aDisplay ||
2915            mozilla::StyleDisplay::RubyTextContainer == aDisplay ||
2916            mozilla::StyleDisplay::Contents == aDisplay;
2917   }
2918 
IsInlineOutsideStylensStyleDisplay2919   bool IsInlineOutsideStyle() const {
2920     return IsDisplayTypeInlineOutside(mDisplay);
2921   }
2922 
IsOriginalDisplayInlineOutsideStylensStyleDisplay2923   bool IsOriginalDisplayInlineOutsideStyle() const {
2924     return IsDisplayTypeInlineOutside(mOriginalDisplay);
2925   }
2926 
IsInnerTableStylensStyleDisplay2927   bool IsInnerTableStyle() const {
2928     return mozilla::StyleDisplay::TableCaption == mDisplay ||
2929            mozilla::StyleDisplay::TableCell == mDisplay ||
2930            mozilla::StyleDisplay::TableRow == mDisplay ||
2931            mozilla::StyleDisplay::TableRowGroup == mDisplay ||
2932            mozilla::StyleDisplay::TableHeaderGroup == mDisplay ||
2933            mozilla::StyleDisplay::TableFooterGroup == mDisplay ||
2934            mozilla::StyleDisplay::TableColumn == mDisplay ||
2935            mozilla::StyleDisplay::TableColumnGroup == mDisplay;
2936   }
2937 
IsFloatingStylensStyleDisplay2938   bool IsFloatingStyle() const {
2939     return mozilla::StyleFloat::None != mFloat;
2940   }
2941 
IsAbsolutelyPositionedStylensStyleDisplay2942   bool IsAbsolutelyPositionedStyle() const {
2943     return NS_STYLE_POSITION_ABSOLUTE == mPosition ||
2944            NS_STYLE_POSITION_FIXED == mPosition;
2945   }
2946 
IsRelativelyPositionedStylensStyleDisplay2947   bool IsRelativelyPositionedStyle() const {
2948     return NS_STYLE_POSITION_RELATIVE == mPosition ||
2949            NS_STYLE_POSITION_STICKY == mPosition;
2950   }
IsPositionForcingStackingContextnsStyleDisplay2951   bool IsPositionForcingStackingContext() const {
2952     return NS_STYLE_POSITION_STICKY == mPosition ||
2953            NS_STYLE_POSITION_FIXED == mPosition;
2954   }
2955 
IsRubyDisplayTypensStyleDisplay2956   static bool IsRubyDisplayType(mozilla::StyleDisplay aDisplay) {
2957     return mozilla::StyleDisplay::Ruby == aDisplay ||
2958            mozilla::StyleDisplay::RubyBase == aDisplay ||
2959            mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||
2960            mozilla::StyleDisplay::RubyText == aDisplay ||
2961            mozilla::StyleDisplay::RubyTextContainer == aDisplay;
2962   }
2963 
IsRubyDisplayTypensStyleDisplay2964   bool IsRubyDisplayType() const {
2965     return IsRubyDisplayType(mDisplay);
2966   }
2967 
IsOutOfFlowStylensStyleDisplay2968   bool IsOutOfFlowStyle() const {
2969     return (IsAbsolutelyPositionedStyle() || IsFloatingStyle());
2970   }
2971 
IsScrollableOverflownsStyleDisplay2972   bool IsScrollableOverflow() const {
2973     // mOverflowX and mOverflowY always match when one of them is
2974     // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
2975     return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
2976            mOverflowX != NS_STYLE_OVERFLOW_CLIP;
2977   }
2978 
IsContainPaintnsStyleDisplay2979   bool IsContainPaint() const {
2980     return NS_STYLE_CONTAIN_PAINT & mContain;
2981   }
2982 
2983   /* Returns whether the element has the -moz-transform property
2984    * or a related property. */
HasTransformStylensStyleDisplay2985   bool HasTransformStyle() const {
2986     return mSpecifiedTransform != nullptr ||
2987            mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
2988            (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
2989   }
2990 
HasPerspectiveStylensStyleDisplay2991   bool HasPerspectiveStyle() const {
2992     return mChildPerspective.GetUnit() == eStyleUnit_Coord;
2993   }
2994 
BackfaceIsHiddennsStyleDisplay2995   bool BackfaceIsHidden() const {
2996     return mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
2997   }
2998 
2999   // These are defined in nsStyleStructInlines.h.
3000 
3001   // The aContextFrame argument on each of these is the frame this
3002   // style struct is for.  If the frame is for SVG text, the return
3003   // value will be massaged to be something that makes sense for
3004   // SVG text.
3005   inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
3006   inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
3007   inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
3008   inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
3009   inline mozilla::StyleDisplay GetDisplay(const nsIFrame* aContextFrame) const;
3010   inline bool IsFloating(const nsIFrame* aContextFrame) const;
3011   inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
3012   inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
3013 
3014   // These methods are defined in nsStyleStructInlines.h.
3015 
3016   /**
3017    * Returns whether the element is a containing block for its
3018    * absolutely positioned descendants.
3019    * aContextFrame is the frame for which this is the nsStyleDisplay.
3020    */
3021   inline bool IsAbsPosContainingBlock(const nsIFrame* aContextFrame) const;
3022 
3023   /**
3024    * The same as IsAbsPosContainingBlock, except skipping the tests that
3025    * are based on the frame rather than the style context (thus
3026    * potentially returning a false positive).
3027    */
3028   template<class StyleContextLike>
3029   inline bool IsAbsPosContainingBlockForAppropriateFrame(
3030                 StyleContextLike* aStyleContext) const;
3031 
3032   /**
3033    * Returns true when the element has the transform property
3034    * or a related property, and supports CSS transforms.
3035    * aContextFrame is the frame for which this is the nsStyleDisplay.
3036    */
3037   inline bool HasTransform(const nsIFrame* aContextFrame) const;
3038 
3039   /**
3040    * Returns true when the element is a containing block for its fixed-pos
3041    * descendants.
3042    * aContextFrame is the frame for which this is the nsStyleDisplay.
3043    */
3044   inline bool IsFixedPosContainingBlock(const nsIFrame* aContextFrame) const;
3045 
3046   /**
3047    * The same as IsFixedPosContainingBlock, except skipping the tests that
3048    * are based on the frame rather than the style context (thus
3049    * potentially returning a false positive).
3050    */
3051   template<class StyleContextLike>
3052   inline bool IsFixedPosContainingBlockForAppropriateFrame(
3053                 StyleContextLike* aStyleContext) const;
3054 
3055 private:
3056   // Helpers for above functions, which do some but not all of the tests
3057   // for them (since transform must be tested separately for each).
3058   template<class StyleContextLike>
3059   inline bool HasAbsPosContainingBlockStyleInternal(
3060                 StyleContextLike* aStyleContext) const;
3061   template<class StyleContextLike>
3062   inline bool HasFixedPosContainingBlockStyleInternal(
3063                 StyleContextLike* aStyleContext) const;
3064 
3065 public:
3066   // Return the 'float' and 'clear' properties, with inline-{start,end} values
3067   // resolved to {left,right} according to the given writing mode. These are
3068   // defined in WritingModes.h.
3069   inline mozilla::StyleFloat PhysicalFloats(mozilla::WritingMode aWM) const;
3070   inline mozilla::StyleClear PhysicalBreakType(mozilla::WritingMode aWM) const;
3071 };
3072 
3073 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
3074 {
3075   explicit nsStyleTable(StyleStructContext aContext);
3076   nsStyleTable(const nsStyleTable& aOther);
3077   ~nsStyleTable();
FinishStylensStyleTable3078   void FinishStyle(nsPresContext* aPresContext) {}
3079 
newnsStyleTable3080   void* operator new(size_t sz, nsStyleTable* aSelf) { return aSelf; }
newnsStyleTable3081   void* operator new(size_t sz, nsPresContext* aContext) {
3082     return aContext->PresShell()->
3083       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz);
3084   }
DestroynsStyleTable3085   void Destroy(nsPresContext* aContext) {
3086     this->~nsStyleTable();
3087     aContext->PresShell()->
3088       FreeByObjectID(mozilla::eArenaObjectID_nsStyleTable, this);
3089   }
3090 
3091   nsChangeHint CalcDifference(const nsStyleTable& aNewData) const;
MaxDifferencensStyleTable3092   static nsChangeHint MaxDifference() {
3093     return nsChangeHint_ReconstructFrame;
3094   }
DifferenceAlwaysHandledForDescendantsnsStyleTable3095   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3096     // CalcDifference never returns the reflow hints that are sometimes
3097     // handled for descendants as hints not handled for descendants.
3098     return nsChangeHint(0);
3099   }
3100 
3101   uint8_t       mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
3102   int32_t       mSpan;          // [reset] the number of columns spanned by a colgroup or col
3103 };
3104 
3105 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder
3106 {
3107   explicit nsStyleTableBorder(StyleStructContext aContext);
3108   nsStyleTableBorder(const nsStyleTableBorder& aOther);
3109   ~nsStyleTableBorder();
FinishStylensStyleTableBorder3110   void FinishStyle(nsPresContext* aPresContext) {}
3111 
newnsStyleTableBorder3112   void* operator new(size_t sz, nsStyleTableBorder* aSelf) { return aSelf; }
newnsStyleTableBorder3113   void* operator new(size_t sz, nsPresContext* aContext) {
3114     return aContext->PresShell()->
3115       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz);
3116   }
DestroynsStyleTableBorder3117   void Destroy(nsPresContext* aContext) {
3118     this->~nsStyleTableBorder();
3119     aContext->PresShell()->
3120       FreeByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, this);
3121   }
3122 
3123   nsChangeHint CalcDifference(const nsStyleTableBorder& aNewData) const;
MaxDifferencensStyleTableBorder3124   static nsChangeHint MaxDifference() {
3125     return nsChangeHint_ReconstructFrame |
3126            NS_STYLE_HINT_REFLOW;
3127   }
DifferenceAlwaysHandledForDescendantsnsStyleTableBorder3128   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3129     // CalcDifference never returns the reflow hints that are sometimes
3130     // handled for descendants as hints not handled for descendants.
3131     return nsChangeHint_NeedReflow |
3132            nsChangeHint_ReflowChangesSizeOrPosition |
3133            nsChangeHint_ClearAncestorIntrinsics;
3134   }
3135 
3136   nscoord       mBorderSpacingCol;// [inherited]
3137   nscoord       mBorderSpacingRow;// [inherited]
3138   uint8_t       mBorderCollapse;// [inherited]
3139   uint8_t       mCaptionSide;   // [inherited]
3140   uint8_t       mEmptyCells;    // [inherited]
3141 };
3142 
3143 enum nsStyleContentType {
3144   eStyleContentType_String        = 1,
3145   eStyleContentType_Image         = 10,
3146   eStyleContentType_Attr          = 20,
3147   eStyleContentType_Counter       = 30,
3148   eStyleContentType_Counters      = 31,
3149   eStyleContentType_OpenQuote     = 40,
3150   eStyleContentType_CloseQuote    = 41,
3151   eStyleContentType_NoOpenQuote   = 42,
3152   eStyleContentType_NoCloseQuote  = 43,
3153   eStyleContentType_AltContent    = 50,
3154   eStyleContentType_Uninitialized
3155 };
3156 
3157 struct nsStyleContentData
3158 {
3159   nsStyleContentType  mType;
3160   union {
3161     char16_t *mString;
3162     imgRequestProxy *mImage;
3163     nsCSSValue::Array* mCounters;
3164   } mContent;
3165 #ifdef DEBUG
3166   bool mImageTracked;
3167 #endif
3168 
nsStyleContentDatansStyleContentData3169   nsStyleContentData()
3170     : mType(eStyleContentType_Uninitialized)
3171 #ifdef DEBUG
3172     , mImageTracked(false)
3173 #endif
3174   {
3175     MOZ_COUNT_CTOR(nsStyleContentData);
3176     mContent.mString = nullptr;
3177   }
3178   nsStyleContentData(const nsStyleContentData&);
3179 
3180   ~nsStyleContentData();
3181   nsStyleContentData& operator=(const nsStyleContentData& aOther);
3182   bool operator==(const nsStyleContentData& aOther) const;
3183 
3184   bool operator!=(const nsStyleContentData& aOther) const {
3185     return !(*this == aOther);
3186   }
3187 
3188   void TrackImage(mozilla::dom::ImageTracker* aImageTracker);
3189   void UntrackImage(mozilla::dom::ImageTracker* aImageTracker);
3190 
SetImagensStyleContentData3191   void SetImage(imgRequestProxy* aRequest)
3192   {
3193     MOZ_ASSERT(!mImageTracked,
3194                "Setting a new image without untracking the old one!");
3195     MOZ_ASSERT(mType == eStyleContentType_Image, "Wrong type!");
3196     NS_IF_ADDREF(mContent.mImage = aRequest);
3197   }
3198 };
3199 
3200 struct nsStyleCounterData
3201 {
3202   nsString  mCounter;
3203   int32_t   mValue;
3204 
3205   bool operator==(const nsStyleCounterData& aOther) const {
3206     return mValue == aOther.mValue && mCounter == aOther.mCounter;
3207   }
3208 
3209   bool operator!=(const nsStyleCounterData& aOther) const {
3210     return !(*this == aOther);
3211   }
3212 };
3213 
3214 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
3215 {
3216   explicit nsStyleContent(StyleStructContext aContext);
3217   nsStyleContent(const nsStyleContent& aContent);
3218   ~nsStyleContent();
FinishStylensStyleContent3219   void FinishStyle(nsPresContext* aPresContext) {}
3220 
newnsStyleContent3221   void* operator new(size_t sz, nsStyleContent* aSelf) { return aSelf; }
newnsStyleContent3222   void* operator new(size_t sz, nsPresContext* aContext) {
3223     return aContext->PresShell()->
3224       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz);
3225   }
3226   void Destroy(nsPresContext* aContext);
3227 
3228   nsChangeHint CalcDifference(const nsStyleContent& aNewData) const;
MaxDifferencensStyleContent3229   static nsChangeHint MaxDifference() {
3230     return nsChangeHint_ReconstructFrame |
3231            NS_STYLE_HINT_REFLOW;
3232   }
DifferenceAlwaysHandledForDescendantsnsStyleContent3233   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3234     // CalcDifference never returns the reflow hints that are sometimes
3235     // handled for descendants as hints not handled for descendants.
3236     return nsChangeHint_NeedReflow |
3237            nsChangeHint_ReflowChangesSizeOrPosition |
3238            nsChangeHint_ClearAncestorIntrinsics;
3239   }
3240 
ContentCountnsStyleContent3241   uint32_t ContentCount() const { return mContents.Length(); } // [reset]
3242 
ContentAtnsStyleContent3243   const nsStyleContentData& ContentAt(uint32_t aIndex) const {
3244     return mContents[aIndex];
3245   }
3246 
ContentAtnsStyleContent3247   nsStyleContentData& ContentAt(uint32_t aIndex) { return mContents[aIndex]; }
3248 
AllocateContentsnsStyleContent3249   void AllocateContents(uint32_t aCount) {
3250     // We need to run the destructors of the elements of mContents, so we
3251     // delete and reallocate even if aCount == mContentCount.  (If
3252     // nsStyleContentData had its members private and managed their
3253     // ownership on setting, we wouldn't need this, but that seems
3254     // unnecessary at this point.)
3255     mContents.Clear();
3256     mContents.SetLength(aCount);
3257   }
3258 
CounterIncrementCountnsStyleContent3259   uint32_t CounterIncrementCount() const { return mIncrements.Length(); }  // [reset]
CounterIncrementAtnsStyleContent3260   const nsStyleCounterData& CounterIncrementAt(uint32_t aIndex) const {
3261     return mIncrements[aIndex];
3262   }
3263 
AllocateCounterIncrementsnsStyleContent3264   void AllocateCounterIncrements(uint32_t aCount) {
3265     mIncrements.Clear();
3266     mIncrements.SetLength(aCount);
3267   }
3268 
SetCounterIncrementAtnsStyleContent3269   void SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
3270     mIncrements[aIndex].mCounter = aCounter;
3271     mIncrements[aIndex].mValue = aIncrement;
3272   }
3273 
CounterResetCountnsStyleContent3274   uint32_t CounterResetCount() const { return mResets.Length(); }  // [reset]
CounterResetAtnsStyleContent3275   const nsStyleCounterData& CounterResetAt(uint32_t aIndex) const {
3276     return mResets[aIndex];
3277   }
3278 
AllocateCounterResetsnsStyleContent3279   void AllocateCounterResets(uint32_t aCount) {
3280     mResets.Clear();
3281     mResets.SetLength(aCount);
3282   }
3283 
SetCounterResetAtnsStyleContent3284   void SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
3285     mResets[aIndex].mCounter = aCounter;
3286     mResets[aIndex].mValue = aValue;
3287   }
3288 
3289 protected:
3290   nsTArray<nsStyleContentData> mContents;
3291   nsTArray<nsStyleCounterData> mIncrements;
3292   nsTArray<nsStyleCounterData> mResets;
3293 };
3294 
3295 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset
3296 {
3297   explicit nsStyleUIReset(StyleStructContext aContext);
3298   nsStyleUIReset(const nsStyleUIReset& aOther);
3299   ~nsStyleUIReset();
FinishStylensStyleUIReset3300   void FinishStyle(nsPresContext* aPresContext) {}
3301 
newnsStyleUIReset3302   void* operator new(size_t sz, nsStyleUIReset* aSelf) { return aSelf; }
newnsStyleUIReset3303   void* operator new(size_t sz, nsPresContext* aContext) {
3304     return aContext->PresShell()->
3305       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz);
3306   }
DestroynsStyleUIReset3307   void Destroy(nsPresContext* aContext) {
3308     this->~nsStyleUIReset();
3309     aContext->PresShell()->
3310       FreeByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, this);
3311   }
3312 
3313   nsChangeHint CalcDifference(const nsStyleUIReset& aNewData) const;
MaxDifferencensStyleUIReset3314   static nsChangeHint MaxDifference() {
3315     return nsChangeHint_ReconstructFrame |
3316            NS_STYLE_HINT_REFLOW;
3317   }
DifferenceAlwaysHandledForDescendantsnsStyleUIReset3318   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3319     // CalcDifference never returns the reflow hints that are sometimes
3320     // handled for descendants as hints not handled for descendants.
3321     return nsChangeHint_NeedReflow |
3322            nsChangeHint_ReflowChangesSizeOrPosition |
3323            nsChangeHint_ClearAncestorIntrinsics;
3324   }
3325 
3326   mozilla::StyleUserSelect     mUserSelect;     // [reset](selection-style)
3327   uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
3328   uint8_t                      mIMEMode;        // [reset]
3329   mozilla::StyleWindowDragging mWindowDragging; // [reset]
3330   uint8_t                      mWindowShadow;   // [reset]
3331 };
3332 
3333 struct nsCursorImage
3334 {
3335   bool mHaveHotspot;
3336   float mHotspotX, mHotspotY;
3337 
3338   nsCursorImage();
3339   nsCursorImage(const nsCursorImage& aOther);
3340   ~nsCursorImage();
3341 
3342   nsCursorImage& operator=(const nsCursorImage& aOther);
3343 
3344   bool operator==(const nsCursorImage& aOther) const;
3345   bool operator!=(const nsCursorImage& aOther) const
3346   {
3347     return !(*this == aOther);
3348   }
3349 
SetImagensCursorImage3350   void SetImage(imgIRequest *aImage) {
3351     if (mImage) {
3352       mImage->UnlockImage();
3353       mImage->RequestDiscard();
3354     }
3355     mImage = aImage;
3356     if (mImage) {
3357       mImage->LockImage();
3358     }
3359   }
GetImagensCursorImage3360   imgIRequest* GetImage() const {
3361     return mImage;
3362   }
3363 
3364 private:
3365   nsCOMPtr<imgIRequest> mImage;
3366 };
3367 
3368 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
3369 {
3370   explicit nsStyleUserInterface(StyleStructContext aContext);
3371   nsStyleUserInterface(const nsStyleUserInterface& aOther);
3372   ~nsStyleUserInterface();
FinishStylensStyleUserInterface3373   void FinishStyle(nsPresContext* aPresContext) {}
3374 
newnsStyleUserInterface3375   void* operator new(size_t sz, nsStyleUserInterface* aSelf) { return aSelf; }
newnsStyleUserInterface3376   void* operator new(size_t sz, nsPresContext* aContext) {
3377     return aContext->PresShell()->
3378       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz);
3379   }
DestroynsStyleUserInterface3380   void Destroy(nsPresContext* aContext) {
3381     this->~nsStyleUserInterface();
3382     aContext->PresShell()->
3383       FreeByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, this);
3384   }
3385 
3386   nsChangeHint CalcDifference(const nsStyleUserInterface& aNewData) const;
MaxDifferencensStyleUserInterface3387   static nsChangeHint MaxDifference() {
3388     return nsChangeHint_ReconstructFrame |
3389            nsChangeHint_NeedReflow |
3390            nsChangeHint_NeedDirtyReflow |
3391            NS_STYLE_HINT_VISUAL |
3392            nsChangeHint_UpdateCursor |
3393            nsChangeHint_NeutralChange;
3394   }
DifferenceAlwaysHandledForDescendantsnsStyleUserInterface3395   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3396     // CalcDifference never returns the reflow hints that are sometimes
3397     // handled for descendants as hints not handled for descendants.
3398     return nsChangeHint_NeedReflow;
3399   }
3400 
3401   mozilla::StyleUserInput   mUserInput;       // [inherited]
3402   mozilla::StyleUserModify  mUserModify;      // [inherited] (modify-content)
3403   mozilla::StyleUserFocus   mUserFocus;       // [inherited] (auto-select)
3404   uint8_t                   mPointerEvents;   // [inherited] see nsStyleConsts.h
3405 
3406   uint8_t mCursor;                            // [inherited] See nsStyleConsts.h
3407   nsTArray<nsCursorImage> mCursorImages;      // [inherited] images and coords
3408 
3409   inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
3410 };
3411 
3412 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
3413 {
3414   explicit nsStyleXUL(StyleStructContext aContext);
3415   nsStyleXUL(const nsStyleXUL& aSource);
3416   ~nsStyleXUL();
FinishStylensStyleXUL3417   void FinishStyle(nsPresContext* aPresContext) {}
3418 
newnsStyleXUL3419   void* operator new(size_t sz, nsStyleXUL* aSelf) { return aSelf; }
newnsStyleXUL3420   void* operator new(size_t sz, nsPresContext* aContext) {
3421     return aContext->PresShell()->
3422       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz);
3423   }
DestroynsStyleXUL3424   void Destroy(nsPresContext* aContext) {
3425     this->~nsStyleXUL();
3426     aContext->PresShell()->
3427       FreeByObjectID(mozilla::eArenaObjectID_nsStyleXUL, this);
3428   }
3429 
3430   nsChangeHint CalcDifference(const nsStyleXUL& aNewData) const;
MaxDifferencensStyleXUL3431   static nsChangeHint MaxDifference() {
3432     return nsChangeHint_ReconstructFrame |
3433            NS_STYLE_HINT_REFLOW;
3434   }
DifferenceAlwaysHandledForDescendantsnsStyleXUL3435   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3436     // CalcDifference never returns the reflow hints that are sometimes
3437     // handled for descendants as hints not handled for descendants.
3438     return nsChangeHint_NeedReflow |
3439            nsChangeHint_ReflowChangesSizeOrPosition |
3440            nsChangeHint_ClearAncestorIntrinsics;
3441   }
3442 
3443   float         mBoxFlex;               // [reset] see nsStyleConsts.h
3444   uint32_t      mBoxOrdinal;            // [reset] see nsStyleConsts.h
3445   mozilla::StyleBoxAlign mBoxAlign;         // [reset]
3446   mozilla::StyleBoxDirection mBoxDirection; // [reset]
3447   mozilla::StyleBoxOrient mBoxOrient;       // [reset]
3448   mozilla::StyleBoxPack mBoxPack;           // [reset]
3449   bool          mStretchStack;          // [reset] see nsStyleConsts.h
3450 };
3451 
3452 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
3453 {
3454   explicit nsStyleColumn(StyleStructContext aContext);
3455   nsStyleColumn(const nsStyleColumn& aSource);
3456   ~nsStyleColumn();
FinishStylensStyleColumn3457   void FinishStyle(nsPresContext* aPresContext) {}
3458 
newnsStyleColumn3459   void* operator new(size_t sz, nsStyleColumn* aSelf) { return aSelf; }
newnsStyleColumn3460   void* operator new(size_t sz, nsPresContext* aContext) {
3461     return aContext->PresShell()->
3462       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz);
3463   }
DestroynsStyleColumn3464   void Destroy(nsPresContext* aContext) {
3465     this->~nsStyleColumn();
3466     aContext->PresShell()->
3467       FreeByObjectID(mozilla::eArenaObjectID_nsStyleColumn, this);
3468   }
3469 
3470   nsChangeHint CalcDifference(const nsStyleColumn& aNewData) const;
MaxDifferencensStyleColumn3471   static nsChangeHint MaxDifference() {
3472     return nsChangeHint_ReconstructFrame |
3473            NS_STYLE_HINT_REFLOW |
3474            nsChangeHint_NeutralChange;
3475   }
DifferenceAlwaysHandledForDescendantsnsStyleColumn3476   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3477     // CalcDifference never returns the reflow hints that are sometimes
3478     // handled for descendants as hints not handled for descendants.
3479     return nsChangeHint_NeedReflow |
3480            nsChangeHint_ReflowChangesSizeOrPosition |
3481            nsChangeHint_ClearAncestorIntrinsics;
3482   }
3483 
3484   /**
3485    * This is the maximum number of columns we can process. It's used in both
3486    * nsColumnSetFrame and nsRuleNode.
3487    */
3488   static const uint32_t kMaxColumnCount = 1000;
3489 
3490   uint32_t     mColumnCount; // [reset] see nsStyleConsts.h
3491   nsStyleCoord mColumnWidth; // [reset] coord, auto
3492   nsStyleCoord mColumnGap;   // [reset] coord, normal
3493 
3494   mozilla::StyleComplexColor mColumnRuleColor; // [reset]
3495   uint8_t      mColumnRuleStyle;  // [reset]
3496   uint8_t      mColumnFill;  // [reset] see nsStyleConsts.h
3497 
SetColumnRuleWidthnsStyleColumn3498   void SetColumnRuleWidth(nscoord aWidth) {
3499     mColumnRuleWidth = NS_ROUND_BORDER_TO_PIXELS(aWidth, mTwipsPerPixel);
3500   }
3501 
GetComputedColumnRuleWidthnsStyleColumn3502   nscoord GetComputedColumnRuleWidth() const {
3503     return (IsVisibleBorderStyle(mColumnRuleStyle) ? mColumnRuleWidth : 0);
3504   }
3505 
3506 protected:
3507   nscoord mColumnRuleWidth;  // [reset] coord
3508   nscoord mTwipsPerPixel;
3509 };
3510 
3511 enum nsStyleSVGPaintType {
3512   eStyleSVGPaintType_None = 1,
3513   eStyleSVGPaintType_Color,
3514   eStyleSVGPaintType_Server,
3515   eStyleSVGPaintType_ContextFill,
3516   eStyleSVGPaintType_ContextStroke
3517 };
3518 
3519 enum nsStyleSVGOpacitySource : uint8_t {
3520   eStyleSVGOpacitySource_Normal,
3521   eStyleSVGOpacitySource_ContextFillOpacity,
3522   eStyleSVGOpacitySource_ContextStrokeOpacity
3523 };
3524 
3525 class nsStyleSVGPaint
3526 {
3527 public:
3528   explicit nsStyleSVGPaint(nsStyleSVGPaintType aType = nsStyleSVGPaintType(0));
3529   nsStyleSVGPaint(const nsStyleSVGPaint& aSource);
3530   ~nsStyleSVGPaint();
3531 
3532   nsStyleSVGPaint& operator=(const nsStyleSVGPaint& aOther);
3533 
Type()3534   nsStyleSVGPaintType Type() const { return mType; }
3535 
3536   void SetNone();
3537   void SetColor(nscolor aColor);
3538   void SetPaintServer(mozilla::css::URLValue* aPaintServer,
3539                       nscolor aFallbackColor);
3540   void SetContextValue(nsStyleSVGPaintType aType,
3541                        nscolor aFallbackColor);
3542 
GetColor()3543   nscolor GetColor() const {
3544     MOZ_ASSERT(mType == eStyleSVGPaintType_Color);
3545     return mPaint.mColor;
3546   }
3547 
GetPaintServer()3548   mozilla::css::URLValue* GetPaintServer() const {
3549     MOZ_ASSERT(mType == eStyleSVGPaintType_Server);
3550     return mPaint.mPaintServer;
3551   }
3552 
GetFallbackColor()3553   nscolor GetFallbackColor() const {
3554     MOZ_ASSERT(mType == eStyleSVGPaintType_Server ||
3555                mType == eStyleSVGPaintType_ContextFill ||
3556                mType == eStyleSVGPaintType_ContextStroke);
3557     return mFallbackColor;
3558   }
3559 
3560   bool operator==(const nsStyleSVGPaint& aOther) const;
3561   bool operator!=(const nsStyleSVGPaint& aOther) const {
3562     return !(*this == aOther);
3563   }
3564 
3565 private:
3566   void Reset();
3567   void Assign(const nsStyleSVGPaint& aOther);
3568 
3569   union {
3570     nscolor mColor;
3571     mozilla::css::URLValue* mPaintServer;
3572   } mPaint;
3573   nsStyleSVGPaintType mType;
3574   nscolor mFallbackColor;
3575 };
3576 
3577 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
3578 {
3579   explicit nsStyleSVG(StyleStructContext aContext);
3580   nsStyleSVG(const nsStyleSVG& aSource);
3581   ~nsStyleSVG();
FinishStylensStyleSVG3582   void FinishStyle(nsPresContext* aPresContext) {}
3583 
newnsStyleSVG3584   void* operator new(size_t sz, nsStyleSVG* aSelf) { return aSelf; }
newnsStyleSVG3585   void* operator new(size_t sz, nsPresContext* aContext) {
3586     return aContext->PresShell()->
3587       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz);
3588   }
DestroynsStyleSVG3589   void Destroy(nsPresContext* aContext) {
3590     this->~nsStyleSVG();
3591     aContext->PresShell()->
3592       FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVG, this);
3593   }
3594 
3595   nsChangeHint CalcDifference(const nsStyleSVG& aNewData) const;
MaxDifferencensStyleSVG3596   static nsChangeHint MaxDifference() {
3597     return nsChangeHint_UpdateEffects |
3598            nsChangeHint_NeedReflow |
3599            nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
3600            nsChangeHint_RepaintFrame;
3601   }
DifferenceAlwaysHandledForDescendantsnsStyleSVG3602   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3603     // CalcDifference never returns nsChangeHint_NeedReflow as a hint
3604     // not handled for descendants, and never returns
3605     // nsChangeHint_ClearAncestorIntrinsics at all.
3606     return nsChangeHint_NeedReflow;
3607   }
3608 
3609   nsStyleSVGPaint  mFill;             // [inherited]
3610   nsStyleSVGPaint  mStroke;           // [inherited]
3611   RefPtr<mozilla::css::URLValue> mMarkerEnd;   // [inherited]
3612   RefPtr<mozilla::css::URLValue> mMarkerMid;   // [inherited]
3613   RefPtr<mozilla::css::URLValue> mMarkerStart; // [inherited]
3614   nsTArray<nsStyleCoord> mStrokeDasharray;  // [inherited] coord, percent, factor
3615 
3616   nsStyleCoord     mStrokeDashoffset; // [inherited] coord, percent, factor
3617   nsStyleCoord     mStrokeWidth;      // [inherited] coord, percent, factor
3618 
3619   float            mFillOpacity;      // [inherited]
3620   float            mStrokeMiterlimit; // [inherited]
3621   float            mStrokeOpacity;    // [inherited]
3622 
3623   mozilla::StyleFillRule    mClipRule;  // [inherited]
3624   uint8_t          mColorInterpolation; // [inherited] see nsStyleConsts.h
3625   uint8_t          mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
3626   mozilla::StyleFillRule    mFillRule;         // [inherited] see nsStyleConsts.h
3627   uint8_t          mPaintOrder;       // [inherited] see nsStyleConsts.h
3628   uint8_t          mShapeRendering;   // [inherited] see nsStyleConsts.h
3629   uint8_t          mStrokeLinecap;    // [inherited] see nsStyleConsts.h
3630   uint8_t          mStrokeLinejoin;   // [inherited] see nsStyleConsts.h
3631   uint8_t          mTextAnchor;       // [inherited] see nsStyleConsts.h
3632 
FillOpacitySourcensStyleSVG3633   nsStyleSVGOpacitySource FillOpacitySource() const {
3634     uint8_t value = (mContextFlags & FILL_OPACITY_SOURCE_MASK) >>
3635                     FILL_OPACITY_SOURCE_SHIFT;
3636     return nsStyleSVGOpacitySource(value);
3637   }
StrokeOpacitySourcensStyleSVG3638   nsStyleSVGOpacitySource StrokeOpacitySource() const {
3639     uint8_t value = (mContextFlags & STROKE_OPACITY_SOURCE_MASK) >>
3640                     STROKE_OPACITY_SOURCE_SHIFT;
3641     return nsStyleSVGOpacitySource(value);
3642   }
StrokeDasharrayFromObjectnsStyleSVG3643   bool StrokeDasharrayFromObject() const {
3644     return mContextFlags & STROKE_DASHARRAY_CONTEXT;
3645   }
StrokeDashoffsetFromObjectnsStyleSVG3646   bool StrokeDashoffsetFromObject() const {
3647     return mContextFlags & STROKE_DASHOFFSET_CONTEXT;
3648   }
StrokeWidthFromObjectnsStyleSVG3649   bool StrokeWidthFromObject() const {
3650     return mContextFlags & STROKE_WIDTH_CONTEXT;
3651   }
3652 
SetFillOpacitySourcensStyleSVG3653   void SetFillOpacitySource(nsStyleSVGOpacitySource aValue) {
3654     mContextFlags = (mContextFlags & ~FILL_OPACITY_SOURCE_MASK) |
3655                     (aValue << FILL_OPACITY_SOURCE_SHIFT);
3656   }
SetStrokeOpacitySourcensStyleSVG3657   void SetStrokeOpacitySource(nsStyleSVGOpacitySource aValue) {
3658     mContextFlags = (mContextFlags & ~STROKE_OPACITY_SOURCE_MASK) |
3659                     (aValue << STROKE_OPACITY_SOURCE_SHIFT);
3660   }
SetStrokeDasharrayFromObjectnsStyleSVG3661   void SetStrokeDasharrayFromObject(bool aValue) {
3662     mContextFlags = (mContextFlags & ~STROKE_DASHARRAY_CONTEXT) |
3663                     (aValue ? STROKE_DASHARRAY_CONTEXT : 0);
3664   }
SetStrokeDashoffsetFromObjectnsStyleSVG3665   void SetStrokeDashoffsetFromObject(bool aValue) {
3666     mContextFlags = (mContextFlags & ~STROKE_DASHOFFSET_CONTEXT) |
3667                     (aValue ? STROKE_DASHOFFSET_CONTEXT : 0);
3668   }
SetStrokeWidthFromObjectnsStyleSVG3669   void SetStrokeWidthFromObject(bool aValue) {
3670     mContextFlags = (mContextFlags & ~STROKE_WIDTH_CONTEXT) |
3671                     (aValue ? STROKE_WIDTH_CONTEXT : 0);
3672   }
3673 
HasMarkernsStyleSVG3674   bool HasMarker() const {
3675     return mMarkerStart || mMarkerMid || mMarkerEnd;
3676   }
3677 
3678   /**
3679    * Returns true if the stroke is not "none" and the stroke-opacity is greater
3680    * than zero. This ignores stroke-widths as that depends on the context.
3681    */
HasStrokensStyleSVG3682   bool HasStroke() const {
3683     return mStroke.Type() != eStyleSVGPaintType_None && mStrokeOpacity > 0;
3684   }
3685 
3686   /**
3687    * Returns true if the fill is not "none" and the fill-opacity is greater
3688    * than zero.
3689    */
HasFillnsStyleSVG3690   bool HasFill() const {
3691     return mFill.Type() != eStyleSVGPaintType_None && mFillOpacity > 0;
3692   }
3693 
3694 private:
3695   // Flags to represent the use of context-fill and context-stroke
3696   // for fill-opacity or stroke-opacity, and context-value for stroke-dasharray,
3697   // stroke-dashoffset and stroke-width.
3698   enum {
3699     FILL_OPACITY_SOURCE_MASK   = 0x03,  // fill-opacity: context-{fill,stroke}
3700     STROKE_OPACITY_SOURCE_MASK = 0x0C,  // stroke-opacity: context-{fill,stroke}
3701     STROKE_DASHARRAY_CONTEXT   = 0x10,  // stroke-dasharray: context-value
3702     STROKE_DASHOFFSET_CONTEXT  = 0x20,  // stroke-dashoffset: context-value
3703     STROKE_WIDTH_CONTEXT       = 0x40,  // stroke-width: context-value
3704     FILL_OPACITY_SOURCE_SHIFT   = 0,
3705     STROKE_OPACITY_SOURCE_SHIFT = 2,
3706   };
3707 
3708   uint8_t          mContextFlags;     // [inherited]
3709 };
3710 
3711 struct nsStyleFilter
3712 {
3713   nsStyleFilter();
3714   nsStyleFilter(const nsStyleFilter& aSource);
3715   ~nsStyleFilter();
FinishStylensStyleFilter3716   void FinishStyle(nsPresContext* aPresContext) {}
3717 
3718   nsStyleFilter& operator=(const nsStyleFilter& aOther);
3719 
3720   bool operator==(const nsStyleFilter& aOther) const;
3721   bool operator!=(const nsStyleFilter& aOther) const {
3722     return !(*this == aOther);
3723   }
3724 
GetTypensStyleFilter3725   uint32_t GetType() const {
3726     return mType;
3727   }
3728 
GetFilterParameternsStyleFilter3729   const nsStyleCoord& GetFilterParameter() const {
3730     NS_ASSERTION(mType != NS_STYLE_FILTER_DROP_SHADOW &&
3731                  mType != NS_STYLE_FILTER_URL &&
3732                  mType != NS_STYLE_FILTER_NONE, "wrong filter type");
3733     return mFilterParameter;
3734   }
3735   void SetFilterParameter(const nsStyleCoord& aFilterParameter,
3736                           int32_t aType);
3737 
GetURLnsStyleFilter3738   mozilla::css::URLValue* GetURL() const {
3739     MOZ_ASSERT(mType == NS_STYLE_FILTER_URL, "wrong filter type");
3740     return mURL;
3741   }
3742 
3743   bool SetURL(mozilla::css::URLValue* aValue);
3744 
GetDropShadownsStyleFilter3745   nsCSSShadowArray* GetDropShadow() const {
3746     NS_ASSERTION(mType == NS_STYLE_FILTER_DROP_SHADOW, "wrong filter type");
3747     return mDropShadow;
3748   }
3749   void SetDropShadow(nsCSSShadowArray* aDropShadow);
3750 
3751 private:
3752   void ReleaseRef();
3753 
3754   uint32_t mType; // see NS_STYLE_FILTER_* constants in nsStyleConsts.h
3755   nsStyleCoord mFilterParameter; // coord, percent, factor, angle
3756   union {
3757     mozilla::css::URLValue* mURL;
3758     nsCSSShadowArray* mDropShadow;
3759   };
3760 };
3761 
3762 template<>
3763 struct nsTArray_CopyChooser<nsStyleFilter>
3764 {
3765   typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
3766 };
3767 
3768 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset
3769 {
3770   explicit nsStyleSVGReset(StyleStructContext aContext);
3771   nsStyleSVGReset(const nsStyleSVGReset& aSource);
3772   ~nsStyleSVGReset();
3773 
3774   // Resolves and tracks the images in mMask.  Only called with a Servo-backed
3775   // style system, where those images must be resolved later than the OMT
3776   // nsStyleSVGReset constructor call.
3777   void FinishStyle(nsPresContext* aPresContext);
3778 
3779   void* operator new(size_t sz, nsStyleSVGReset* aSelf) { return aSelf; }
3780   void* operator new(size_t sz, nsPresContext* aContext) {
3781     return aContext->PresShell()->
3782       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
3783   }
3784   void Destroy(nsPresContext* aContext);
3785 
3786   nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
3787   static nsChangeHint MaxDifference() {
3788     return nsChangeHint_UpdateEffects |
3789            nsChangeHint_UpdateOverflow |
3790            nsChangeHint_NeutralChange |
3791            nsChangeHint_RepaintFrame |
3792            nsChangeHint_UpdateBackgroundPosition |
3793            NS_STYLE_HINT_REFLOW;
3794   }
3795   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3796     // CalcDifference never returns the reflow hints that are sometimes
3797     // handled for descendants as hints not handled for descendants.
3798     return nsChangeHint_NeedReflow |
3799            nsChangeHint_ReflowChangesSizeOrPosition |
3800            nsChangeHint_ClearAncestorIntrinsics;
3801   }
3802 
3803   bool HasClipPath() const {
3804     return mClipPath.GetType() != mozilla::StyleShapeSourceType::None;
3805   }
3806 
3807   bool HasNonScalingStroke() const {
3808     return mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE;
3809   }
3810 
3811   nsStyleImageLayers    mMask;
3812   mozilla::StyleClipPath mClipPath;   // [reset]
3813   nscolor          mStopColor;        // [reset]
3814   nscolor          mFloodColor;       // [reset]
3815   nscolor          mLightingColor;    // [reset]
3816 
3817   float            mStopOpacity;      // [reset]
3818   float            mFloodOpacity;     // [reset]
3819 
3820   uint8_t          mDominantBaseline; // [reset] see nsStyleConsts.h
3821   uint8_t          mVectorEffect;     // [reset] see nsStyleConsts.h
3822   uint8_t          mMaskType;         // [reset] see nsStyleConsts.h
3823 };
3824 
3825 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables
3826 {
3827   explicit nsStyleVariables(StyleStructContext aContext);
3828   nsStyleVariables(const nsStyleVariables& aSource);
3829   ~nsStyleVariables();
3830   void FinishStyle(nsPresContext* aPresContext) {}
3831 
3832   void* operator new(size_t sz, nsStyleVariables* aSelf) { return aSelf; }
3833   void* operator new(size_t sz, nsPresContext* aContext) {
3834     return aContext->PresShell()->
3835       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz);
3836   }
3837   void Destroy(nsPresContext* aContext) {
3838     this->~nsStyleVariables();
3839     aContext->PresShell()->
3840       FreeByObjectID(mozilla::eArenaObjectID_nsStyleVariables, this);
3841   }
3842 
3843   nsChangeHint CalcDifference(const nsStyleVariables& aNewData) const;
3844   static nsChangeHint MaxDifference() {
3845     return nsChangeHint(0);
3846   }
3847   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3848     // CalcDifference never returns nsChangeHint_NeedReflow or
3849     // nsChangeHint_ClearAncestorIntrinsics at all.
3850     return nsChangeHint(0);
3851   }
3852 
3853   mozilla::CSSVariableValues mVariables;
3854 };
3855 
3856 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects
3857 {
3858   explicit nsStyleEffects(StyleStructContext aContext);
3859   nsStyleEffects(const nsStyleEffects& aSource);
3860   ~nsStyleEffects();
3861   void FinishStyle(nsPresContext* aPresContext) {}
3862 
3863   void* operator new(size_t sz, nsStyleEffects* aSelf) { return aSelf; }
3864   void* operator new(size_t sz, nsPresContext* aContext) {
3865     return aContext->PresShell()->
3866       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleEffects, sz);
3867   }
3868   void Destroy(nsPresContext* aContext) {
3869     this->~nsStyleEffects();
3870     aContext->PresShell()->
3871       FreeByObjectID(mozilla::eArenaObjectID_nsStyleEffects, this);
3872   }
3873 
3874   nsChangeHint CalcDifference(const nsStyleEffects& aNewData) const;
3875   static nsChangeHint MaxDifference() {
3876     return nsChangeHint_AllReflowHints |
3877            nsChangeHint_UpdateOverflow |
3878            nsChangeHint_SchedulePaint |
3879            nsChangeHint_RepaintFrame |
3880            nsChangeHint_UpdateOpacityLayer |
3881            nsChangeHint_UpdateUsesOpacity |
3882            nsChangeHint_UpdateContainingBlock |
3883            nsChangeHint_UpdateEffects |
3884            nsChangeHint_NeutralChange;
3885   }
3886   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3887     // CalcDifference never returns the reflow hints that are sometimes
3888     // handled for descendants as hints not handled for descendants.
3889     return nsChangeHint_NeedReflow |
3890            nsChangeHint_ReflowChangesSizeOrPosition |
3891            nsChangeHint_ClearAncestorIntrinsics;
3892   }
3893 
3894   bool HasFilters() const {
3895     return !mFilters.IsEmpty();
3896   }
3897 
3898   nsTArray<nsStyleFilter>  mFilters;   // [reset]
3899   RefPtr<nsCSSShadowArray> mBoxShadow; // [reset] nullptr for 'none'
3900   nsRect  mClip;                       // [reset] offsets from UL border edge
3901   float   mOpacity;                    // [reset]
3902   uint8_t mClipFlags;                  // [reset] see nsStyleConsts.h
3903   uint8_t mMixBlendMode;               // [reset] see nsStyleConsts.h
3904 };
3905 
3906 #define STATIC_ASSERT_TYPE_LAYOUTS_MATCH(T1, T2)                               \
3907   static_assert(sizeof(T1) == sizeof(T2),                                      \
3908       "Size mismatch between " #T1 " and " #T2);                               \
3909   static_assert(alignof(T1) == alignof(T2),                                    \
3910       "Align mismatch between " #T1 " and " #T2);                              \
3911 
3912 #define STATIC_ASSERT_FIELD_OFFSET_MATCHES(T1, T2, field)                      \
3913   static_assert(offsetof(T1, field) == offsetof(T2, field),                    \
3914       "Field offset mismatch of " #field " between " #T1 " and " #T2);         \
3915 
3916 /**
3917  * These *_Simple types are used to map Gecko types to layout-equivalent but
3918  * simpler Rust types, to aid Rust binding generation.
3919  *
3920  * If something in this types or the assertions below needs to change, ask
3921  * bholley, heycam or emilio before!
3922  *
3923  * <div rustbindgen="true" replaces="nsPoint">
3924  */
3925 struct nsPoint_Simple {
3926   nscoord x, y;
3927 };
3928 
3929 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsPoint, nsPoint_Simple);
3930 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsPoint, nsPoint_Simple, x);
3931 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsPoint, nsPoint_Simple, y);
3932 
3933 /**
3934  * <div rustbindgen="true" replaces="nsMargin">
3935  */
3936 struct nsMargin_Simple {
3937   nscoord top, right, bottom, left;
3938 };
3939 
3940 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsMargin, nsMargin_Simple);
3941 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, top);
3942 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, right);
3943 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, bottom);
3944 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, left);
3945 
3946 /**
3947  * <div rustbindgen="true" replaces="nsRect">
3948  */
3949 struct nsRect_Simple {
3950   nscoord x, y, width, height;
3951 };
3952 
3953 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsRect, nsRect_Simple);
3954 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, x);
3955 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, y);
3956 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, width);
3957 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, height);
3958 
3959 /**
3960  * <div rustbindgen="true" replaces="nsSize">
3961  */
3962 struct nsSize_Simple {
3963   nscoord width, height;
3964 };
3965 
3966 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsSize, nsSize_Simple);
3967 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsSize, nsSize_Simple, width);
3968 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsSize, nsSize_Simple, height);
3969 
3970 /**
3971  * <div rustbindgen="true" replaces="UniquePtr">
3972  *
3973  * TODO(Emilio): This is a workaround and we should be able to get rid of this
3974  * one.
3975  */
3976 template<typename T, typename Deleter = mozilla::DefaultDelete<T>>
3977 struct UniquePtr_Simple {
3978   T* mPtr;
3979 };
3980 
3981 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(mozilla::UniquePtr<int>, UniquePtr_Simple<int>);
3982 
3983 /**
3984  * <div rustbindgen replaces="nsTArray"></div>
3985  */
3986 template<typename T>
3987 class nsTArray_Simple {
3988   T* mBuffer;
3989 public:
3990   // The existence of a destructor here prevents bindgen from deriving the Clone
3991   // trait via a simple memory copy.
3992   ~nsTArray_Simple() {};
3993 };
3994 
3995 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<nsStyleImageLayers::Layer>,
3996                                  nsTArray_Simple<nsStyleImageLayers::Layer>);
3997 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleTransition>,
3998                                  nsTArray_Simple<mozilla::StyleTransition>);
3999 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleAnimation>,
4000                                  nsTArray_Simple<mozilla::StyleAnimation>);
4001 
4002 #endif /* nsStyleStruct_h___ */
4003