layout/style/nsStyleStruct.h

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * structs that contain the data provided by nsStyleContext, the
     8  * internal API for computed style data for an element
     9  */
    11 #ifndef nsStyleStruct_h___
    12 #define nsStyleStruct_h___
    14 #include "mozilla/Attributes.h"
    15 #include "mozilla/CSSVariableValues.h"
    16 #include "nsColor.h"
    17 #include "nsCoord.h"
    18 #include "nsMargin.h"
    19 #include "nsRect.h"
    20 #include "nsFont.h"
    21 #include "nsStyleCoord.h"
    22 #include "nsStyleConsts.h"
    23 #include "nsChangeHint.h"
    24 #include "nsPresContext.h"
    25 #include "nsCOMPtr.h"
    26 #include "nsCOMArray.h"
    27 #include "nsTArray.h"
    28 #include "nsIAtom.h"
    29 #include "nsCSSValue.h"
    30 #include "imgRequestProxy.h"
    31 #include "Orientation.h"
    32 #include <algorithm>
    34 class nsIFrame;
    35 class nsIURI;
    36 class imgIContainer;
    38 // Includes nsStyleStructID.
    39 #include "nsStyleStructFwd.h"
    41 // Bits for each struct.
    42 // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
    43 #define NS_STYLE_INHERIT_MASK              0x000ffffff
    45 // Additional bits for nsStyleContext's mBits:
    46 // See nsStyleContext::HasTextDecorationLines
    47 #define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000
    48 // See nsStyleContext::HasPseudoElementData.
    49 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA   0x002000000
    50 // See nsStyleContext::RelevantLinkIsVisited
    51 #define NS_STYLE_RELEVANT_LINK_VISITED     0x004000000
    52 // See nsStyleContext::IsStyleIfVisited
    53 #define NS_STYLE_IS_STYLE_IF_VISITED       0x008000000
    54 // See nsStyleContext::GetPseudoEnum
    55 #define NS_STYLE_CONTEXT_TYPE_MASK         0x1f0000000
    56 #define NS_STYLE_CONTEXT_TYPE_SHIFT        28
    58 // Additional bits for nsRuleNode's mDependentBits:
    59 #define NS_RULE_NODE_GC_MARK                0x02000000
    60 #define NS_RULE_NODE_USED_DIRECTLY          0x04000000
    61 #define NS_RULE_NODE_IS_IMPORTANT           0x08000000
    62 #define NS_RULE_NODE_LEVEL_MASK             0xf0000000
    63 #define NS_RULE_NODE_LEVEL_SHIFT            28
    65 // The lifetime of these objects is managed by the presshell's arena.
    67 struct nsStyleFont {
    68   nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext);
    69   nsStyleFont(const nsStyleFont& aStyleFont);
    70   nsStyleFont(nsPresContext *aPresContext);
    71 private:
    72   void Init(nsPresContext *aPresContext);
    73 public:
    74   ~nsStyleFont(void) {
    75     MOZ_COUNT_DTOR(nsStyleFont);
    76   }
    78   nsChangeHint CalcDifference(const nsStyleFont& aOther) const;
    79   static nsChangeHint MaxDifference() {
    80     return NS_STYLE_HINT_REFLOW;
    81   }
    82   static nsChangeHint MaxDifferenceNeverInherited() {
    83     // CalcDifference never returns nsChangeHint_NeedReflow or
    84     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
    85     return NS_CombineHint(nsChangeHint_NeedReflow,
    86                           nsChangeHint_ClearAncestorIntrinsics);
    87   }
    88   static nsChangeHint CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2);
    90   static nscoord ZoomText(nsPresContext* aPresContext, nscoord aSize);
    91   static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
    93   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
    94   void Destroy(nsPresContext* aContext);
    96   void EnableZoom(nsPresContext* aContext, bool aEnable);
    98   nsFont  mFont;        // [inherited]
    99   nscoord mSize;        // [inherited] Our "computed size". Can be different
   100                         // from mFont.size which is our "actual size" and is
   101                         // enforced to be >= the user's preferred min-size.
   102                         // mFont.size should be used for display purposes
   103                         // while mSize is the value to return in
   104                         // getComputedStyle() for example.
   105   uint8_t mGenericID;   // [inherited] generic CSS font family, if any;
   106                         // value is a kGenericFont_* constant, see nsFont.h.
   108   // MathML scriptlevel support
   109   int8_t  mScriptLevel;          // [inherited]
   110   // MathML  mathvariant support
   111   uint8_t mMathVariant;          // [inherited]
   112   // MathML displaystyle support
   113   uint8_t mMathDisplay;         // [inherited]
   115   // was mLanguage set based on a lang attribute in the document?
   116   bool mExplicitLanguage;        // [inherited]
   118   // should calls to ZoomText() and UnZoomText() be made to the font
   119   // size on this nsStyleFont?
   120   bool mAllowZoom;               // [inherited]
   122   // The value mSize would have had if scriptminsize had never been applied
   123   nscoord mScriptUnconstrainedSize;
   124   nscoord mScriptMinSize;        // [inherited] length
   125   float   mScriptSizeMultiplier; // [inherited]
   126   nsCOMPtr<nsIAtom> mLanguage;   // [inherited]
   127 };
   129 struct nsStyleGradientStop {
   130   nsStyleCoord mLocation; // percent, coord, calc, none
   131   nscolor mColor;
   132 };
   134 class nsStyleGradient MOZ_FINAL {
   135 public:
   136   nsStyleGradient();
   137   uint8_t mShape;  // NS_STYLE_GRADIENT_SHAPE_*
   138   uint8_t mSize;   // NS_STYLE_GRADIENT_SIZE_*;
   139                    // not used (must be FARTHEST_CORNER) for linear shape
   140   bool mRepeating;
   141   bool mLegacySyntax;
   143   nsStyleCoord mBgPosX; // percent, coord, calc, none
   144   nsStyleCoord mBgPosY; // percent, coord, calc, none
   145   nsStyleCoord mAngle;  // none, angle
   147   nsStyleCoord mRadiusX; // percent, coord, calc, none
   148   nsStyleCoord mRadiusY; // percent, coord, calc, none
   150   // stops are in the order specified in the stylesheet
   151   nsTArray<nsStyleGradientStop> mStops;
   153   bool operator==(const nsStyleGradient& aOther) const;
   154   bool operator!=(const nsStyleGradient& aOther) const {
   155     return !(*this == aOther);
   156   }
   158   bool IsOpaque();
   159   bool HasCalc();
   160   uint32_t Hash(PLDHashNumber aHash);
   162   NS_INLINE_DECL_REFCOUNTING(nsStyleGradient)
   164 private:
   165   // Private destructor, to discourage deletion outside of Release():
   166   ~nsStyleGradient() {}
   168   nsStyleGradient(const nsStyleGradient& aOther) MOZ_DELETE;
   169   nsStyleGradient& operator=(const nsStyleGradient& aOther) MOZ_DELETE;
   170 };
   172 enum nsStyleImageType {
   173   eStyleImageType_Null,
   174   eStyleImageType_Image,
   175   eStyleImageType_Gradient,
   176   eStyleImageType_Element
   177 };
   179 /**
   180  * Represents a paintable image of one of the following types.
   181  * (1) A real image loaded from an external source.
   182  * (2) A CSS linear or radial gradient.
   183  * (3) An element within a document, or an <img>, <video>, or <canvas> element
   184  *     not in a document.
   185  * (*) Optionally a crop rect can be set to paint a partial (rectangular)
   186  * region of an image. (Currently, this feature is only supported with an
   187  * image of type (1)).
   188  */
   189 struct nsStyleImage {
   190   nsStyleImage();
   191   ~nsStyleImage();
   192   nsStyleImage(const nsStyleImage& aOther);
   193   nsStyleImage& operator=(const nsStyleImage& aOther);
   195   void SetNull();
   196   void SetImageData(imgIRequest* aImage);
   197   void TrackImage(nsPresContext* aContext);
   198   void UntrackImage(nsPresContext* aContext);
   199   void SetGradientData(nsStyleGradient* aGradient);
   200   void SetElementId(const char16_t* aElementId);
   201   void SetCropRect(nsStyleSides* aCropRect);
   203   nsStyleImageType GetType() const {
   204     return mType;
   205   }
   206   imgIRequest* GetImageData() const {
   207     NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "Data is not an image!");
   208     NS_ABORT_IF_FALSE(mImageTracked,
   209                       "Should be tracking any image we're going to use!");
   210     return mImage;
   211   }
   212   nsStyleGradient* GetGradientData() const {
   213     NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
   214     return mGradient;
   215   }
   216   const char16_t* GetElementId() const {
   217     NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
   218     return mElementId;
   219   }
   220   nsStyleSides* GetCropRect() const {
   221     NS_ASSERTION(mType == eStyleImageType_Image,
   222                  "Only image data can have a crop rect");
   223     return mCropRect;
   224   }
   226   /**
   227    * Compute the actual crop rect in pixels, using the source image bounds.
   228    * The computation involves converting percentage unit to pixel unit and
   229    * clamping each side value to fit in the source image bounds.
   230    * @param aActualCropRect the computed actual crop rect.
   231    * @param aIsEntireImage true iff |aActualCropRect| is identical to the
   232    * source image bounds.
   233    * @return true iff |aActualCropRect| holds a meaningful value.
   234    */
   235   bool ComputeActualCropRect(nsIntRect& aActualCropRect,
   236                                bool* aIsEntireImage = nullptr) const;
   238   /**
   239    * Starts the decoding of a image.
   240    */
   241   nsresult StartDecoding() const;
   242   /**
   243    * @return true if the item is definitely opaque --- i.e., paints every
   244    * pixel within its bounds opaquely, and the bounds contains at least a pixel.
   245    */
   246   bool IsOpaque() const;
   247   /**
   248    * @return true if this image is fully loaded, and its size is calculated;
   249    * always returns true if |mType| is |eStyleImageType_Gradient| or
   250    * |eStyleImageType_Element|.
   251    */
   252   bool IsComplete() const;
   253   /**
   254    * @return true if this image is loaded without error;
   255    * always returns true if |mType| is |eStyleImageType_Gradient| or
   256    * |eStyleImageType_Element|.
   257    */
   258   bool IsLoaded() const;
   259   /**
   260    * @return true if it is 100% confident that this image contains no pixel
   261    * to draw.
   262    */
   263   bool IsEmpty() const {
   264     // There are some other cases when the image will be empty, for example
   265     // when the crop rect is empty. However, checking the emptiness of crop
   266     // rect is non-trivial since each side value can be specified with
   267     // percentage unit, which can not be evaluated until the source image size
   268     // is available. Therefore, we currently postpone the evaluation of crop
   269     // rect until the actual rendering time --- alternatively until GetOpaqueRegion()
   270     // is called.
   271     return mType == eStyleImageType_Null;
   272   }
   274   bool operator==(const nsStyleImage& aOther) const;
   275   bool operator!=(const nsStyleImage& aOther) const {
   276     return !(*this == aOther);
   277   }
   279   bool ImageDataEquals(const nsStyleImage& aOther) const
   280   {
   281     return GetType() == eStyleImageType_Image &&
   282            aOther.GetType() == eStyleImageType_Image &&
   283            GetImageData() == aOther.GetImageData();
   284   }
   286   // These methods are used for the caller to caches the sub images created
   287   // during a border-image paint operation
   288   inline void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const;
   289   inline imgIContainer* GetSubImage(uint8_t aIndex) const;
   291 private:
   292   void DoCopy(const nsStyleImage& aOther);
   294   // Cache for border-image painting.
   295   nsCOMArray<imgIContainer> mSubImages;
   297   nsStyleImageType mType;
   298   union {
   299     imgIRequest* mImage;
   300     nsStyleGradient* mGradient;
   301     char16_t* mElementId;
   302   };
   303   // This is _currently_ used only in conjunction with eStyleImageType_Image.
   304   nsAutoPtr<nsStyleSides> mCropRect;
   305 #ifdef DEBUG
   306   bool mImageTracked;
   307 #endif
   308 };
   310 struct nsStyleColor {
   311   nsStyleColor(nsPresContext* aPresContext);
   312   nsStyleColor(const nsStyleColor& aOther);
   313   ~nsStyleColor(void) {
   314     MOZ_COUNT_DTOR(nsStyleColor);
   315   }
   317   nsChangeHint CalcDifference(const nsStyleColor& aOther) const;
   318   static nsChangeHint MaxDifference() {
   319     return NS_STYLE_HINT_VISUAL;
   320   }
   321   static nsChangeHint MaxDifferenceNeverInherited() {
   322     // CalcDifference never returns nsChangeHint_NeedReflow or
   323     // nsChangeHint_ClearAncestorIntrinsics at all.
   324     return nsChangeHint(0);
   325   }
   327   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
   328     return aContext->AllocateFromShell(sz);
   329   }
   330   void Destroy(nsPresContext* aContext) {
   331     this->~nsStyleColor();
   332     aContext->FreeToShell(sizeof(nsStyleColor), this);
   333   }
   335   // Don't add ANY members to this struct!  We can achieve caching in the rule
   336   // tree (rather than the style tree) by letting color stay by itself! -dwh
   337   nscolor mColor;                 // [inherited]
   338 };
   340 struct nsStyleBackground {
   341   nsStyleBackground();
   342   nsStyleBackground(const nsStyleBackground& aOther);
   343   ~nsStyleBackground();
   345   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
   346     return aContext->AllocateFromShell(sz);
   347   }
   348   void Destroy(nsPresContext* aContext);
   350   nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
   351   static nsChangeHint MaxDifference() {
   352     return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
   353   }
   354   static nsChangeHint MaxDifferenceNeverInherited() {
   355     // CalcDifference never returns nsChangeHint_NeedReflow or
   356     // nsChangeHint_ClearAncestorIntrinsics at all.
   357     return nsChangeHint(0);
   358   }
   360   struct Position;
   361   friend struct Position;
   362   struct Position {
   363     typedef nsStyleCoord::Calc PositionCoord;
   364     PositionCoord mXPosition, mYPosition;
   366     // Initialize nothing
   367     Position() {}
   369     // Initialize to initial values
   370     void SetInitialValues();
   372     // True if the effective background image position described by this depends
   373     // on the size of the corresponding frame.
   374     bool DependsOnPositioningAreaSize() const {
   375       return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
   376     }
   378     bool operator==(const Position& aOther) const {
   379       return mXPosition == aOther.mXPosition &&
   380              mYPosition == aOther.mYPosition;
   381     }
   382     bool operator!=(const Position& aOther) const {
   383       return !(*this == aOther);
   384     }
   385   };
   387   struct Size;
   388   friend struct Size;
   389   struct Size {
   390     struct Dimension : public nsStyleCoord::Calc {
   391       nscoord ResolveLengthPercentage(nscoord aAvailable) const {
   392         double d = double(mPercent) * double(aAvailable) + double(mLength);
   393         if (d < 0.0)
   394           return 0;
   395         return NSToCoordRoundWithClamp(float(d));
   396       }
   397     };
   398     Dimension mWidth, mHeight;
   400     nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
   401       NS_ABORT_IF_FALSE(mWidthType == eLengthPercentage,
   402                         "resolving non-length/percent dimension!");
   403       return mWidth.ResolveLengthPercentage(aBgPositioningArea.width);
   404     }
   406     nscoord ResolveHeightLengthPercentage(const nsSize& aBgPositioningArea) const {
   407       NS_ABORT_IF_FALSE(mHeightType == eLengthPercentage,
   408                         "resolving non-length/percent dimension!");
   409       return mHeight.ResolveLengthPercentage(aBgPositioningArea.height);
   410     }
   412     // Except for eLengthPercentage, Dimension types which might change
   413     // how a layer is painted when the corresponding frame's dimensions
   414     // change *must* precede all dimension types which are agnostic to
   415     // frame size; see DependsOnDependsOnPositioningAreaSizeSize.
   416     enum DimensionType {
   417       // If one of mWidth and mHeight is eContain or eCover, then both are.
   418       // Also, these two values must equal the corresponding values in
   419       // kBackgroundSizeKTable.
   420       eContain, eCover,
   422       eAuto,
   423       eLengthPercentage,
   424       eDimensionType_COUNT
   425     };
   426     uint8_t mWidthType, mHeightType;
   428     // True if the effective image size described by this depends on the size of
   429     // the corresponding frame, when aImage (which must not have null type) is
   430     // the background image.
   431     bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
   433     // Initialize nothing
   434     Size() {}
   436     // Initialize to initial values
   437     void SetInitialValues();
   439     bool operator==(const Size& aOther) const;
   440     bool operator!=(const Size& aOther) const {
   441       return !(*this == aOther);
   442     }
   443   };
   445   struct Repeat;
   446   friend struct Repeat;
   447   struct Repeat {
   448     uint8_t mXRepeat, mYRepeat;
   450     // Initialize nothing
   451     Repeat() {}
   453     // Initialize to initial values
   454     void SetInitialValues();
   456     bool operator==(const Repeat& aOther) const {
   457       return mXRepeat == aOther.mXRepeat &&
   458              mYRepeat == aOther.mYRepeat;
   459     }
   460     bool operator!=(const Repeat& aOther) const {
   461       return !(*this == aOther);
   462     }
   463   };
   465   struct Layer;
   466   friend struct Layer;
   467   struct Layer {
   468     uint8_t mAttachment;                // [reset] See nsStyleConsts.h
   469     uint8_t mClip;                      // [reset] See nsStyleConsts.h
   470     uint8_t mOrigin;                    // [reset] See nsStyleConsts.h
   471     uint8_t mBlendMode;                 // [reset] See nsStyleConsts.h
   472     Repeat mRepeat;                     // [reset] See nsStyleConsts.h
   473     Position mPosition;                 // [reset]
   474     nsStyleImage mImage;                // [reset]
   475     Size mSize;                         // [reset]
   477     // Initializes only mImage
   478     Layer();
   479     ~Layer();
   481     // Register/unregister images with the document. We do this only
   482     // after the dust has settled in ComputeBackgroundData.
   483     void TrackImages(nsPresContext* aContext) {
   484       if (mImage.GetType() == eStyleImageType_Image)
   485         mImage.TrackImage(aContext);
   486     }
   487     void UntrackImages(nsPresContext* aContext) {
   488       if (mImage.GetType() == eStyleImageType_Image)
   489         mImage.UntrackImage(aContext);
   490     }
   492     void SetInitialValues();
   494     // True if the rendering of this layer might change when the size
   495     // of the background positioning area changes.  This is true for any
   496     // non-solid-color background whose position or size depends on
   497     // the size of the positioning area.  It's also true for SVG images
   498     // whose root <svg> node has a viewBox.
   499     bool RenderingMightDependOnPositioningAreaSizeChange() const;
   501     // An equality operator that compares the images using URL-equality
   502     // rather than pointer-equality.
   503     bool operator==(const Layer& aOther) const;
   504     bool operator!=(const Layer& aOther) const {
   505       return !(*this == aOther);
   506     }
   507   };
   509   // The (positive) number of computed values of each property, since
   510   // the lengths of the lists are independent.
   511   uint32_t mAttachmentCount,
   512            mClipCount,
   513            mOriginCount,
   514            mRepeatCount,
   515            mPositionCount,
   516            mImageCount,
   517            mSizeCount,
   518            mBlendModeCount;
   519   // Layers are stored in an array, matching the top-to-bottom order in
   520   // which they are specified in CSS.  The number of layers to be used
   521   // should come from the background-image property.  We create
   522   // additional |Layer| objects for *any* property, not just
   523   // background-image.  This means that the bottommost layer that
   524   // callers in layout care about (which is also the one whose
   525   // background-clip applies to the background-color) may not be last
   526   // layer.  In layers below the bottom layer, properties will be
   527   // uninitialized unless their count, above, indicates that they are
   528   // present.
   529   nsAutoTArray<Layer, 1> mLayers;
   531   const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
   533   #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(var_, stylebg_) \
   534     for (uint32_t var_ = (stylebg_) ? (stylebg_)->mImageCount : 1; var_-- != 0; )
   535   #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, stylebg_, start_, count_) \
   536     NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < ((stylebg_) ? (stylebg_)->mImageCount : 1), "Invalid layer start!"); \
   537     NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
   538     for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
   540   nscolor mBackgroundColor;       // [reset]
   542   // FIXME: This (now background-break in css3-background) should
   543   // probably move into a different struct so that everything in
   544   // nsStyleBackground is set by the background shorthand.
   545   uint8_t mBackgroundInlinePolicy; // [reset] See nsStyleConsts.h
   547   // True if this background is completely transparent.
   548   bool IsTransparent() const;
   550   // We have to take slower codepaths for fixed background attachment,
   551   // but we don't want to do that when there's no image.
   552   // Not inline because it uses an nsCOMPtr<imgIRequest>
   553   // FIXME: Should be in nsStyleStructInlines.h.
   554   bool HasFixedBackground() const;
   555 };
   557 // See https://bugzilla.mozilla.org/show_bug.cgi?id=271586#c43 for why
   558 // this is hard to replace with 'currentColor'.
   559 #define BORDER_COLOR_FOREGROUND   0x20
   560 #define OUTLINE_COLOR_INITIAL     0x80
   561 // FOREGROUND | INITIAL(OUTLINE)
   562 #define BORDER_COLOR_SPECIAL      0xA0
   563 #define BORDER_STYLE_MASK         0x1F
   565 #define NS_SPACING_MARGIN   0
   566 #define NS_SPACING_PADDING  1
   567 #define NS_SPACING_BORDER   2
   570 struct nsStyleMargin {
   571   nsStyleMargin(void);
   572   nsStyleMargin(const nsStyleMargin& aMargin);
   573   ~nsStyleMargin(void) {
   574     MOZ_COUNT_DTOR(nsStyleMargin);
   575   }
   577   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
   578   void Destroy(nsPresContext* aContext);
   580   void RecalcData();
   581   nsChangeHint CalcDifference(const nsStyleMargin& aOther) const;
   582   static nsChangeHint MaxDifference() {
   583     return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
   584                            NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
   585                                           nsChangeHint_NeedDirtyReflow));
   586   }
   587   static nsChangeHint MaxDifferenceNeverInherited() {
   588     // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
   589     // nsChangeHint_NeedReflow as inherited hints.
   590     return nsChangeHint(0);
   591   }
   593   nsStyleSides  mMargin;          // [reset] coord, percent, calc, auto
   595   bool IsWidthDependent() const { return !mHasCachedMargin; }
   596   bool GetMargin(nsMargin& aMargin) const
   597   {
   598     if (mHasCachedMargin) {
   599       aMargin = mCachedMargin;
   600       return true;
   601     }
   602     return false;
   603   }
   605 protected:
   606   bool          mHasCachedMargin;
   607   nsMargin      mCachedMargin;
   608 };
   611 struct nsStylePadding {
   612   nsStylePadding(void);
   613   nsStylePadding(const nsStylePadding& aPadding);
   614   ~nsStylePadding(void) {
   615     MOZ_COUNT_DTOR(nsStylePadding);
   616   }
   618   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
   619   void Destroy(nsPresContext* aContext);
   621   void RecalcData();
   622   nsChangeHint CalcDifference(const nsStylePadding& aOther) const;
   623   static nsChangeHint MaxDifference() {
   624     return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
   625                            nsChangeHint_ClearDescendantIntrinsics);
   626   }
   627   static nsChangeHint MaxDifferenceNeverInherited() {
   628     // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as an
   629     // inherited hint.
   630     return nsChangeHint(0);
   631   }
   633   nsStyleSides  mPadding;         // [reset] coord, percent, calc
   635   bool IsWidthDependent() const { return !mHasCachedPadding; }
   636   bool GetPadding(nsMargin& aPadding) const
   637   {
   638     if (mHasCachedPadding) {
   639       aPadding = mCachedPadding;
   640       return true;
   641     }
   642     return false;
   643   }
   645 protected:
   646   bool          mHasCachedPadding;
   647   nsMargin      mCachedPadding;
   648 };
   650 struct nsBorderColors {
   651   nsBorderColors* mNext;
   652   nscolor mColor;
   654   nsBorderColors() : mNext(nullptr), mColor(NS_RGB(0,0,0)) {}
   655   nsBorderColors(const nscolor& aColor) : mNext(nullptr), mColor(aColor) {}
   656   ~nsBorderColors();
   658   nsBorderColors* Clone() const { return Clone(true); }
   660   static bool Equal(const nsBorderColors* c1,
   661                       const nsBorderColors* c2) {
   662     if (c1 == c2)
   663       return true;
   664     while (c1 && c2) {
   665       if (c1->mColor != c2->mColor)
   666         return false;
   667       c1 = c1->mNext;
   668       c2 = c2->mNext;
   669     }
   670     // both should be nullptr if these are equal, otherwise one
   671     // has more colors than another
   672     return !c1 && !c2;
   673   }
   675 private:
   676   nsBorderColors* Clone(bool aDeep) const;
   677 };
   679 struct nsCSSShadowItem {
   680   nscoord mXOffset;
   681   nscoord mYOffset;
   682   nscoord mRadius;
   683   nscoord mSpread;
   685   nscolor      mColor;
   686   bool mHasColor; // Whether mColor should be used
   687   bool mInset;
   689   nsCSSShadowItem() : mHasColor(false) {
   690     MOZ_COUNT_CTOR(nsCSSShadowItem);
   691   }
   692   ~nsCSSShadowItem() {
   693     MOZ_COUNT_DTOR(nsCSSShadowItem);
   694   }
   696   bool operator==(const nsCSSShadowItem& aOther) const {
   697     return (mXOffset == aOther.mXOffset &&
   698             mYOffset == aOther.mYOffset &&
   699             mRadius == aOther.mRadius &&
   700             mHasColor == aOther.mHasColor &&
   701             mSpread == aOther.mSpread &&
   702             mInset == aOther.mInset &&
   703             (!mHasColor || mColor == aOther.mColor));
   704   }
   705   bool operator!=(const nsCSSShadowItem& aOther) const {
   706     return !(*this == aOther);
   707   }
   708 };
   710 class nsCSSShadowArray MOZ_FINAL {
   711   public:
   712     void* operator new(size_t aBaseSize, uint32_t aArrayLen) {
   713       // We can allocate both this nsCSSShadowArray and the
   714       // actual array in one allocation. The amount of memory to
   715       // allocate is equal to the class's size + the number of bytes for all
   716       // but the first array item (because aBaseSize includes one
   717       // item, see the private declarations)
   718       return ::operator new(aBaseSize +
   719                             (aArrayLen - 1) * sizeof(nsCSSShadowItem));
   720     }
   722     nsCSSShadowArray(uint32_t aArrayLen) :
   723       mLength(aArrayLen)
   724     {
   725       MOZ_COUNT_CTOR(nsCSSShadowArray);
   726       for (uint32_t i = 1; i < mLength; ++i) {
   727         // Make sure we call the constructors of each nsCSSShadowItem
   728         // (the first one is called for us because we declared it under private)
   729         new (&mArray[i]) nsCSSShadowItem();
   730       }
   731     }
   733 private:
   734     // Private destructor, to discourage deletion outside of Release():
   735     ~nsCSSShadowArray() {
   736       MOZ_COUNT_DTOR(nsCSSShadowArray);
   737       for (uint32_t i = 1; i < mLength; ++i) {
   738         mArray[i].~nsCSSShadowItem();
   739       }
   740     }
   742 public:
   743     uint32_t Length() const { return mLength; }
   744     nsCSSShadowItem* ShadowAt(uint32_t i) {
   745       NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
   746       return &mArray[i];
   747     }
   748     const nsCSSShadowItem* ShadowAt(uint32_t i) const {
   749       NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
   750       return &mArray[i];
   751     }
   753     bool HasShadowWithInset(bool aInset) {
   754       for (uint32_t i = 0; i < mLength; ++i) {
   755         if (mArray[i].mInset == aInset)
   756           return true;
   757       }
   758       return false;
   759     }
   761     bool operator==(const nsCSSShadowArray& aOther) const {
   762       if (mLength != aOther.Length())
   763         return false;
   765       for (uint32_t i = 0; i < mLength; ++i) {
   766         if (ShadowAt(i) != aOther.ShadowAt(i))
   767           return false;
   768       }
   770       return true;
   771     }
   773     NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray)
   775   private:
   776     uint32_t mLength;
   777     nsCSSShadowItem mArray[1]; // This MUST be the last item
   778 };
   780 // Border widths are rounded to the nearest-below integer number of pixels,
   781 // but values between zero and one device pixels are always rounded up to
   782 // one device pixel.
   783 #define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
   784   ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
   785 // Outline offset is rounded to the nearest integer number of pixels, but values
   786 // between zero and one device pixels are always rounded up to one device pixel.
   787 // Note that the offset can be negative.
   788 #define NS_ROUND_OFFSET_TO_PIXELS(l,tpp) \
   789   (((l) == 0) ? 0 : \
   790     ((l) > 0) ? std::max( (tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) : \
   791                 std::min(-(tpp), ((l) - ((tpp) / 2)) / (tpp) * (tpp)))
   793 // Returns if the given border style type is visible or not
   794 static bool IsVisibleBorderStyle(uint8_t aStyle)
   795 {
   796   return (aStyle != NS_STYLE_BORDER_STYLE_NONE &&
   797           aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
   798 }
   800 struct nsStyleBorder {
   801   nsStyleBorder(nsPresContext* aContext);
   802   nsStyleBorder(const nsStyleBorder& aBorder);
   803   ~nsStyleBorder();
   805   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
   806   void Destroy(nsPresContext* aContext);
   808   nsChangeHint CalcDifference(const nsStyleBorder& aOther) const;
   809   static nsChangeHint MaxDifference() {
   810     return NS_CombineHint(NS_STYLE_HINT_REFLOW,
   811                           nsChangeHint_BorderStyleNoneChange);
   812   }
   813   static nsChangeHint MaxDifferenceNeverInherited() {
   814     // CalcDifference never returns nsChangeHint_NeedReflow or
   815     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
   816     return NS_CombineHint(nsChangeHint_NeedReflow,
   817                           nsChangeHint_ClearAncestorIntrinsics);
   818   }
   820   void EnsureBorderColors() {
   821     if (!mBorderColors) {
   822       mBorderColors = new nsBorderColors*[4];
   823       if (mBorderColors)
   824         for (int32_t i = 0; i < 4; i++)
   825           mBorderColors[i] = nullptr;
   826     }
   827   }
   829   void ClearBorderColors(mozilla::css::Side aSide) {
   830     if (mBorderColors && mBorderColors[aSide]) {
   831       delete mBorderColors[aSide];
   832       mBorderColors[aSide] = nullptr;
   833     }
   834   }
   836   // Return whether aStyle is a visible style.  Invisible styles cause
   837   // the relevant computed border width to be 0.
   838   // Note that this does *not* consider the effects of 'border-image':
   839   // if border-style is none, but there is a loaded border image,
   840   // HasVisibleStyle will be false even though there *is* a border.
   841   bool HasVisibleStyle(mozilla::css::Side aSide) const
   842   {
   843     return IsVisibleBorderStyle(GetBorderStyle(aSide));
   844   }
   846   // aBorderWidth is in twips
   847   void SetBorderWidth(mozilla::css::Side aSide, nscoord aBorderWidth)
   848   {
   849     nscoord roundedWidth =
   850       NS_ROUND_BORDER_TO_PIXELS(aBorderWidth, mTwipsPerPixel);
   851     mBorder.Side(aSide) = roundedWidth;
   852     if (HasVisibleStyle(aSide))
   853       mComputedBorder.Side(aSide) = roundedWidth;
   854   }
   856   // Get the computed border (plus rounding).  This does consider the
   857   // effects of 'border-style: none', but does not consider
   858   // 'border-image'.
   859   const nsMargin& GetComputedBorder() const
   860   {
   861     return mComputedBorder;
   862   }
   864   bool HasBorder() const
   865   {
   866     return mComputedBorder != nsMargin(0,0,0,0) || !mBorderImageSource.IsEmpty();
   867   }
   869   // Get the actual border width for a particular side, in appunits.  Note that
   870   // this is zero if and only if there is no border to be painted for this
   871   // side.  That is, this value takes into account the border style and the
   872   // value is rounded to the nearest device pixel by NS_ROUND_BORDER_TO_PIXELS.
   873   nscoord GetComputedBorderWidth(mozilla::css::Side aSide) const
   874   {
   875     return GetComputedBorder().Side(aSide);
   876   }
   878   uint8_t GetBorderStyle(mozilla::css::Side aSide) const
   879   {
   880     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
   881     return (mBorderStyle[aSide] & BORDER_STYLE_MASK);
   882   }
   884   void SetBorderStyle(mozilla::css::Side aSide, uint8_t aStyle)
   885   {
   886     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
   887     mBorderStyle[aSide] &= ~BORDER_STYLE_MASK;
   888     mBorderStyle[aSide] |= (aStyle & BORDER_STYLE_MASK);
   889     mComputedBorder.Side(aSide) =
   890       (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
   891   }
   893   inline bool IsBorderImageLoaded() const
   894   {
   895     return mBorderImageSource.IsLoaded();
   896   }
   898   // Defined in nsStyleStructInlines.h
   899   inline nsresult RequestDecode();
   901   void GetBorderColor(mozilla::css::Side aSide, nscolor& aColor,
   902                       bool& aForeground) const
   903   {
   904     aForeground = false;
   905     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
   906     if ((mBorderStyle[aSide] & BORDER_COLOR_SPECIAL) == 0)
   907       aColor = mBorderColor[aSide];
   908     else if (mBorderStyle[aSide] & BORDER_COLOR_FOREGROUND)
   909       aForeground = true;
   910     else
   911       NS_NOTREACHED("OUTLINE_COLOR_INITIAL should not be set here");
   912   }
   914   void SetBorderColor(mozilla::css::Side aSide, nscolor aColor)
   915   {
   916     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
   917     mBorderColor[aSide] = aColor;
   918     mBorderStyle[aSide] &= ~BORDER_COLOR_SPECIAL;
   919   }
   921   void TrackImage(nsPresContext* aContext)
   922   {
   923     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
   924       mBorderImageSource.TrackImage(aContext);
   925     }
   926   }
   927   void UntrackImage(nsPresContext* aContext)
   928   {
   929     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
   930       mBorderImageSource.UntrackImage(aContext);
   931     }
   932   }
   934   nsMargin GetImageOutset() const;
   936   void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
   937   {
   938     if (!mBorderColors)
   939       *aColors = nullptr;
   940     else
   941       *aColors = mBorderColors[aIndex];
   942   }
   944   void AppendBorderColor(int32_t aIndex, nscolor aColor)
   945   {
   946     NS_ASSERTION(aIndex >= 0 && aIndex <= 3, "bad side for composite border color");
   947     nsBorderColors* colorEntry = new nsBorderColors(aColor);
   948     if (!mBorderColors[aIndex])
   949       mBorderColors[aIndex] = colorEntry;
   950     else {
   951       nsBorderColors* last = mBorderColors[aIndex];
   952       while (last->mNext)
   953         last = last->mNext;
   954       last->mNext = colorEntry;
   955     }
   956     mBorderStyle[aIndex] &= ~BORDER_COLOR_SPECIAL;
   957   }
   959   void SetBorderToForeground(mozilla::css::Side aSide)
   960   {
   961     NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
   962     mBorderStyle[aSide] &= ~BORDER_COLOR_SPECIAL;
   963     mBorderStyle[aSide] |= BORDER_COLOR_FOREGROUND;
   964   }
   966   imgIRequest* GetBorderImageRequest() const
   967   {
   968     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
   969       return mBorderImageSource.GetImageData();
   970     }
   971     return nullptr;
   972   }
   974 public:
   975   nsBorderColors** mBorderColors;        // [reset] composite (stripe) colors
   976   nsRefPtr<nsCSSShadowArray> mBoxShadow; // [reset] nullptr for 'none'
   978 public:
   979   nsStyleCorners mBorderRadius;       // [reset] coord, percent
   980   nsStyleImage   mBorderImageSource;  // [reset]
   981   nsStyleSides   mBorderImageSlice;   // [reset] factor, percent
   982   nsStyleSides   mBorderImageWidth;   // [reset] length, factor, percent, auto
   983   nsStyleSides   mBorderImageOutset;  // [reset] length, factor
   985   uint8_t        mBorderImageFill;    // [reset]
   986   uint8_t        mBorderImageRepeatH; // [reset] see nsStyleConsts.h
   987   uint8_t        mBorderImageRepeatV; // [reset]
   988   uint8_t        mFloatEdge;          // [reset]
   990 protected:
   991   // mComputedBorder holds the CSS2.1 computed border-width values.
   992   // In particular, these widths take into account the border-style
   993   // for the relevant side, and the values are rounded to the nearest
   994   // device pixel (which is not part of the definition of computed
   995   // values). The presence or absence of a border-image does not
   996   // affect border-width values.
   997   nsMargin      mComputedBorder;
   999   // mBorder holds the nscoord values for the border widths as they
  1000   // would be if all the border-style values were visible (not hidden
  1001   // or none).  This member exists so that when we create structs
  1002   // using the copy constructor during style resolution the new
  1003   // structs will know what the specified values of the border were in
  1004   // case they have more specific rules setting the border style.
  1005   //
  1006   // Note that this isn't quite the CSS specified value, since this
  1007   // has had the enumerated border widths converted to lengths, and
  1008   // all lengths converted to twips.  But it's not quite the computed
  1009   // value either. The values are rounded to the nearest device pixel.
  1010   nsMargin      mBorder;
  1012   uint8_t       mBorderStyle[4];  // [reset] See nsStyleConsts.h
  1013   nscolor       mBorderColor[4];  // [reset] the colors to use for a simple
  1014                                   // border.  not used for -moz-border-colors
  1015 private:
  1016   nscoord       mTwipsPerPixel;
  1018   nsStyleBorder& operator=(const nsStyleBorder& aOther) MOZ_DELETE;
  1019 };
  1022 struct nsStyleOutline {
  1023   nsStyleOutline(nsPresContext* aPresContext);
  1024   nsStyleOutline(const nsStyleOutline& aOutline);
  1025   ~nsStyleOutline(void) {
  1026     MOZ_COUNT_DTOR(nsStyleOutline);
  1029   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1030     return aContext->AllocateFromShell(sz);
  1032   void Destroy(nsPresContext* aContext) {
  1033     this->~nsStyleOutline();
  1034     aContext->FreeToShell(sizeof(nsStyleOutline), this);
  1037   void RecalcData(nsPresContext* aContext);
  1038   nsChangeHint CalcDifference(const nsStyleOutline& aOther) const;
  1039   static nsChangeHint MaxDifference() {
  1040     return NS_CombineHint(nsChangeHint_AllReflowHints,
  1041                           nsChangeHint_RepaintFrame);
  1043   static nsChangeHint MaxDifferenceNeverInherited() {
  1044     // CalcDifference never returns nsChangeHint_NeedReflow or
  1045     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  1046     return NS_CombineHint(nsChangeHint_NeedReflow,
  1047                           nsChangeHint_ClearAncestorIntrinsics);
  1050   nsStyleCorners  mOutlineRadius; // [reset] coord, percent, calc
  1052   // Note that this is a specified value.  You can get the actual values
  1053   // with GetOutlineWidth.  You cannot get the computed value directly.
  1054   nsStyleCoord  mOutlineWidth;    // [reset] coord, enum (see nsStyleConsts.h)
  1055   nscoord       mOutlineOffset;   // [reset]
  1057   bool GetOutlineWidth(nscoord& aWidth) const
  1059     if (mHasCachedOutline) {
  1060       aWidth = mCachedOutlineWidth;
  1061       return true;
  1063     return false;
  1066   uint8_t GetOutlineStyle(void) const
  1068     return (mOutlineStyle & BORDER_STYLE_MASK);
  1071   void SetOutlineStyle(uint8_t aStyle)
  1073     mOutlineStyle &= ~BORDER_STYLE_MASK;
  1074     mOutlineStyle |= (aStyle & BORDER_STYLE_MASK);
  1077   // false means initial value
  1078   bool GetOutlineColor(nscolor& aColor) const
  1080     if ((mOutlineStyle & BORDER_COLOR_SPECIAL) == 0) {
  1081       aColor = mOutlineColor;
  1082       return true;
  1084     return false;
  1087   void SetOutlineColor(nscolor aColor)
  1089     mOutlineColor = aColor;
  1090     mOutlineStyle &= ~BORDER_COLOR_SPECIAL;
  1093   void SetOutlineInitialColor()
  1095     mOutlineStyle |= OUTLINE_COLOR_INITIAL;
  1098   bool GetOutlineInitialColor() const
  1100     return !!(mOutlineStyle & OUTLINE_COLOR_INITIAL);
  1103 protected:
  1104   // This value is the actual value, so it's rounded to the nearest device
  1105   // pixel.
  1106   nscoord       mCachedOutlineWidth;
  1108   nscolor       mOutlineColor;    // [reset]
  1110   bool          mHasCachedOutline;
  1111   uint8_t       mOutlineStyle;    // [reset] See nsStyleConsts.h
  1113   nscoord       mTwipsPerPixel;
  1114 };
  1117 struct nsStyleList {
  1118   nsStyleList(void);
  1119   nsStyleList(const nsStyleList& aStyleList);
  1120   ~nsStyleList(void);
  1122   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1123     return aContext->AllocateFromShell(sz);
  1125   void Destroy(nsPresContext* aContext) {
  1126     this->~nsStyleList();
  1127     aContext->FreeToShell(sizeof(nsStyleList), this);
  1130   nsChangeHint CalcDifference(const nsStyleList& aOther) const;
  1131   static nsChangeHint MaxDifference() {
  1132     return NS_STYLE_HINT_FRAMECHANGE;
  1134   static nsChangeHint MaxDifferenceNeverInherited() {
  1135     // CalcDifference never returns nsChangeHint_NeedReflow or
  1136     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  1137     return NS_CombineHint(nsChangeHint_NeedReflow,
  1138                           nsChangeHint_ClearAncestorIntrinsics);
  1141   imgRequestProxy* GetListStyleImage() const { return mListStyleImage; }
  1142   void SetListStyleImage(imgRequestProxy* aReq)
  1144     if (mListStyleImage)
  1145       mListStyleImage->UnlockImage();
  1146     mListStyleImage = aReq;
  1147     if (mListStyleImage)
  1148       mListStyleImage->LockImage();
  1151   uint8_t   mListStyleType;             // [inherited] See nsStyleConsts.h
  1152   uint8_t   mListStylePosition;         // [inherited]
  1153 private:
  1154   nsRefPtr<imgRequestProxy> mListStyleImage; // [inherited]
  1155   nsStyleList& operator=(const nsStyleList& aOther) MOZ_DELETE;
  1156 public:
  1157   nsRect        mImageRegion;           // [inherited] the rect to use within an image
  1158 };
  1160 // Computed value of the grid-template-columns or grid-columns-rows property
  1161 // (but *not* grid-template-areas.)
  1162 // http://dev.w3.org/csswg/css-grid/#track-sizing
  1163 //
  1164 // This represents either:
  1165 // * none:
  1166 //   mIsSubgrid is false, all three arrays are empty
  1167 // * <track-list>:
  1168 //   mIsSubgrid is false,
  1169 //   mMinTrackSizingFunctions and mMaxTrackSizingFunctions
  1170 //   are of identical non-zero size,
  1171 //   and mLineNameLists is one element longer than that.
  1172 //   (Delimiting N columns requires N+1 lines:
  1173 //   one before each track, plus one at the very end.)
  1174 //
  1175 //   An omitted <line-names> is still represented in mLineNameLists,
  1176 //   as an empty sub-array.
  1177 //
  1178 //   A <track-size> specified as a single <track-breadth> is represented
  1179 //   as identical min and max sizing functions.
  1180 //
  1181 //   The units for nsStyleCoord are:
  1182 //   * eStyleUnit_Percent represents a <percentage>
  1183 //   * eStyleUnit_FlexFraction represents a <flex> flexible fraction
  1184 //   * eStyleUnit_Coord represents a <length>
  1185 //   * eStyleUnit_Enumerated represents min-content or max-content
  1186 // * subgrid <line-name-list>?:
  1187 //   mIsSubgrid is true,
  1188 //   mLineNameLists may or may not be empty,
  1189 //   mMinTrackSizingFunctions and mMaxTrackSizingFunctions are empty.
  1190 struct nsStyleGridTemplate {
  1191   bool mIsSubgrid;
  1192   nsTArray<nsTArray<nsString>> mLineNameLists;
  1193   nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
  1194   nsTArray<nsStyleCoord> mMaxTrackSizingFunctions;
  1196   nsStyleGridTemplate()
  1197     : mIsSubgrid(false)
  1201   inline bool operator!=(const nsStyleGridTemplate& aOther) const {
  1202     return mLineNameLists != aOther.mLineNameLists ||
  1203            mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
  1204            mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions;
  1206 };
  1208 struct nsStyleGridLine {
  1209   // http://dev.w3.org/csswg/css-grid/#typedef-grid-line
  1210   bool mHasSpan;
  1211   int32_t mInteger;  // 0 means not provided
  1212   nsString mLineName;  // Empty string means not provided.
  1214   nsStyleGridLine()
  1215     : mHasSpan(false)
  1216     , mInteger(0)
  1217     // mLineName get its default constructor, the empty string
  1221   nsStyleGridLine(const nsStyleGridLine& aOther)
  1223     (*this) = aOther;
  1226   void operator=(const nsStyleGridLine& aOther)
  1228     mHasSpan = aOther.mHasSpan;
  1229     mInteger = aOther.mInteger;
  1230     mLineName = aOther.mLineName;
  1233   bool operator!=(const nsStyleGridLine& aOther) const
  1235     return mHasSpan != aOther.mHasSpan ||
  1236            mInteger != aOther.mInteger ||
  1237            mLineName != aOther.mLineName;
  1240   void SetToInteger(uint32_t value)
  1242     mHasSpan = false;
  1243     mInteger = value;
  1244     mLineName.Truncate();
  1247   void SetAuto()
  1249     mHasSpan = false;
  1250     mInteger = 0;
  1251     mLineName.Truncate();
  1254   bool IsAuto() const
  1256     bool haveInitialValues =  mInteger == 0 && mLineName.IsEmpty();
  1257     MOZ_ASSERT(!(haveInitialValues && mHasSpan),
  1258                "should not have 'span' when other components are "
  1259                "at their initial values");
  1260     return haveInitialValues;
  1262 };
  1264 struct nsStylePosition {
  1265   nsStylePosition(void);
  1266   nsStylePosition(const nsStylePosition& aOther);
  1267   ~nsStylePosition(void);
  1269   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1270     return aContext->AllocateFromShell(sz);
  1272   void Destroy(nsPresContext* aContext) {
  1273     this->~nsStylePosition();
  1274     aContext->FreeToShell(sizeof(nsStylePosition), this);
  1277   nsChangeHint CalcDifference(const nsStylePosition& aOther) const;
  1278   static nsChangeHint MaxDifference() {
  1279     return NS_CombineHint(NS_STYLE_HINT_REFLOW,
  1280                           nsChangeHint(nsChangeHint_RecomputePosition |
  1281                                        nsChangeHint_UpdateOverflow));
  1283   static nsChangeHint MaxDifferenceNeverInherited() {
  1284     // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
  1285     // nsChangeHint_NeedReflow as inherited hints.
  1286     return nsChangeHint(0);
  1289   nsStyleSides  mOffset;                // [reset] coord, percent, calc, auto
  1290   nsStyleCoord  mWidth;                 // [reset] coord, percent, enum, calc, auto
  1291   nsStyleCoord  mMinWidth;              // [reset] coord, percent, enum, calc
  1292   nsStyleCoord  mMaxWidth;              // [reset] coord, percent, enum, calc, none
  1293   nsStyleCoord  mHeight;                // [reset] coord, percent, calc, auto
  1294   nsStyleCoord  mMinHeight;             // [reset] coord, percent, calc
  1295   nsStyleCoord  mMaxHeight;             // [reset] coord, percent, calc, none
  1296   nsStyleCoord  mFlexBasis;             // [reset] coord, percent, enum, calc, auto
  1297   nsStyleCoord  mGridAutoColumnsMin;    // [reset] coord, percent, enum, calc, flex
  1298   nsStyleCoord  mGridAutoColumnsMax;    // [reset] coord, percent, enum, calc, flex
  1299   nsStyleCoord  mGridAutoRowsMin;       // [reset] coord, percent, enum, calc, flex
  1300   nsStyleCoord  mGridAutoRowsMax;       // [reset] coord, percent, enum, calc, flex
  1301   uint8_t       mGridAutoFlow;          // [reset] enumerated. See nsStyleConsts.h
  1302   uint8_t       mBoxSizing;             // [reset] see nsStyleConsts.h
  1303   uint8_t       mAlignContent;          // [reset] see nsStyleConsts.h
  1304   uint8_t       mAlignItems;            // [reset] see nsStyleConsts.h
  1305   uint8_t       mAlignSelf;             // [reset] see nsStyleConsts.h
  1306   uint8_t       mFlexDirection;         // [reset] see nsStyleConsts.h
  1307   uint8_t       mFlexWrap;              // [reset] see nsStyleConsts.h
  1308   uint8_t       mJustifyContent;        // [reset] see nsStyleConsts.h
  1309   int32_t       mOrder;                 // [reset] integer
  1310   float         mFlexGrow;              // [reset] float
  1311   float         mFlexShrink;            // [reset] float
  1312   nsStyleCoord  mZIndex;                // [reset] integer, auto
  1313   // NOTE: Fields so far can be memcpy()'ed, while following fields
  1314   // need to have their copy constructor called when we're being copied.
  1315   // See nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
  1316   // in nsStyleStruct.cpp
  1317   nsStyleGridTemplate mGridTemplateColumns;
  1318   nsStyleGridTemplate mGridTemplateRows;
  1320   // nullptr for 'none'
  1321   nsRefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
  1323   // We represent the "grid-auto-position" property in two parts:
  1324   nsStyleGridLine mGridAutoPositionColumn;
  1325   nsStyleGridLine mGridAutoPositionRow;
  1327   nsStyleGridLine mGridColumnStart;
  1328   nsStyleGridLine mGridColumnEnd;
  1329   nsStyleGridLine mGridRowStart;
  1330   nsStyleGridLine mGridRowEnd;
  1332   bool WidthDependsOnContainer() const
  1333     { return WidthCoordDependsOnContainer(mWidth); }
  1334   bool MinWidthDependsOnContainer() const
  1335     { return WidthCoordDependsOnContainer(mMinWidth); }
  1336   bool MaxWidthDependsOnContainer() const
  1337     { return WidthCoordDependsOnContainer(mMaxWidth); }
  1339   // Note that these functions count 'auto' as depending on the
  1340   // container since that's the case for absolutely positioned elements.
  1341   // However, some callers do not care about this case and should check
  1342   // for it, since it is the most common case.
  1343   // FIXME: We should probably change the assumption to be the other way
  1344   // around.
  1345   bool HeightDependsOnContainer() const
  1346     { return HeightCoordDependsOnContainer(mHeight); }
  1347   bool MinHeightDependsOnContainer() const
  1348     { return HeightCoordDependsOnContainer(mMinHeight); }
  1349   bool MaxHeightDependsOnContainer() const
  1350     { return HeightCoordDependsOnContainer(mMaxHeight); }
  1352   bool OffsetHasPercent(mozilla::css::Side aSide) const
  1354     return mOffset.Get(aSide).HasPercent();
  1357 private:
  1358   static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
  1359   static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
  1361     return aCoord.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
  1362            aCoord.HasPercent();
  1364 };
  1366 struct nsStyleTextOverflowSide {
  1367   nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
  1369   bool operator==(const nsStyleTextOverflowSide& aOther) const {
  1370     return mType == aOther.mType &&
  1371            (mType != NS_STYLE_TEXT_OVERFLOW_STRING ||
  1372             mString == aOther.mString);
  1374   bool operator!=(const nsStyleTextOverflowSide& aOther) const {
  1375     return !(*this == aOther);
  1378   nsString mString;
  1379   uint8_t  mType;
  1380 };
  1382 struct nsStyleTextOverflow {
  1383   nsStyleTextOverflow() : mLogicalDirections(true) {}
  1384   bool operator==(const nsStyleTextOverflow& aOther) const {
  1385     return mLeft == aOther.mLeft && mRight == aOther.mRight;
  1387   bool operator!=(const nsStyleTextOverflow& aOther) const {
  1388     return !(*this == aOther);
  1391   // Returns the value to apply on the left side.
  1392   const nsStyleTextOverflowSide& GetLeft(uint8_t aDirection) const {
  1393     NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
  1394                  aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
  1395     return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
  1396              mLeft : mRight;
  1399   // Returns the value to apply on the right side.
  1400   const nsStyleTextOverflowSide& GetRight(uint8_t aDirection) const {
  1401     NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
  1402                  aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
  1403     return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
  1404              mRight : mLeft;
  1407   // Returns the first value that was specified.
  1408   const nsStyleTextOverflowSide* GetFirstValue() const {
  1409     return mLogicalDirections ? &mRight : &mLeft;
  1412   // Returns the second value, or null if there was only one value specified.
  1413   const nsStyleTextOverflowSide* GetSecondValue() const {
  1414     return mLogicalDirections ? nullptr : &mRight;
  1417   nsStyleTextOverflowSide mLeft;  // start side when mLogicalDirections is true
  1418   nsStyleTextOverflowSide mRight; // end side when mLogicalDirections is true
  1419   bool mLogicalDirections;  // true when only one value was specified
  1420 };
  1422 struct nsStyleTextReset {
  1423   nsStyleTextReset(void);
  1424   nsStyleTextReset(const nsStyleTextReset& aOther);
  1425   ~nsStyleTextReset(void);
  1427   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1428     return aContext->AllocateFromShell(sz);
  1430   void Destroy(nsPresContext* aContext) {
  1431     this->~nsStyleTextReset();
  1432     aContext->FreeToShell(sizeof(nsStyleTextReset), this);
  1435   uint8_t GetDecorationStyle() const
  1437     return (mTextDecorationStyle & BORDER_STYLE_MASK);
  1440   void SetDecorationStyle(uint8_t aStyle)
  1442     NS_ABORT_IF_FALSE((aStyle & BORDER_STYLE_MASK) == aStyle,
  1443                       "style doesn't fit");
  1444     mTextDecorationStyle &= ~BORDER_STYLE_MASK;
  1445     mTextDecorationStyle |= (aStyle & BORDER_STYLE_MASK);
  1448   void GetDecorationColor(nscolor& aColor, bool& aForeground) const
  1450     aForeground = false;
  1451     if ((mTextDecorationStyle & BORDER_COLOR_SPECIAL) == 0) {
  1452       aColor = mTextDecorationColor;
  1453     } else if (mTextDecorationStyle & BORDER_COLOR_FOREGROUND) {
  1454       aForeground = true;
  1455     } else {
  1456       NS_NOTREACHED("OUTLINE_COLOR_INITIAL should not be set here");
  1460   void SetDecorationColor(nscolor aColor)
  1462     mTextDecorationColor = aColor;
  1463     mTextDecorationStyle &= ~BORDER_COLOR_SPECIAL;
  1466   void SetDecorationColorToForeground()
  1468     mTextDecorationStyle &= ~BORDER_COLOR_SPECIAL;
  1469     mTextDecorationStyle |= BORDER_COLOR_FOREGROUND;
  1472   nsChangeHint CalcDifference(const nsStyleTextReset& aOther) const;
  1473   static nsChangeHint MaxDifference() {
  1474     return NS_STYLE_HINT_REFLOW;
  1476   static nsChangeHint MaxDifferenceNeverInherited() {
  1477     // CalcDifference never returns nsChangeHint_NeedReflow or
  1478     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  1479     return NS_CombineHint(nsChangeHint_NeedReflow,
  1480                           nsChangeHint_ClearAncestorIntrinsics);
  1483   nsStyleCoord  mVerticalAlign;         // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
  1484   nsStyleTextOverflow mTextOverflow;    // [reset] enum, string
  1486   uint8_t mTextDecorationLine;          // [reset] see nsStyleConsts.h
  1487   uint8_t mUnicodeBidi;                 // [reset] see nsStyleConsts.h
  1488 protected:
  1489   uint8_t mTextDecorationStyle;         // [reset] see nsStyleConsts.h
  1491   nscolor mTextDecorationColor;         // [reset] the colors to use for a decoration lines, not used at currentColor
  1492 };
  1494 struct nsStyleText {
  1495   nsStyleText(void);
  1496   nsStyleText(const nsStyleText& aOther);
  1497   ~nsStyleText(void);
  1499   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1500     return aContext->AllocateFromShell(sz);
  1502   void Destroy(nsPresContext* aContext) {
  1503     this->~nsStyleText();
  1504     aContext->FreeToShell(sizeof(nsStyleText), this);
  1507   nsChangeHint CalcDifference(const nsStyleText& aOther) const;
  1508   static nsChangeHint MaxDifference() {
  1509     return NS_STYLE_HINT_FRAMECHANGE;
  1511   static nsChangeHint MaxDifferenceNeverInherited() {
  1512     // CalcDifference never returns nsChangeHint_NeedReflow or
  1513     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  1514     return NS_CombineHint(nsChangeHint_NeedReflow,
  1515                           nsChangeHint_ClearAncestorIntrinsics);
  1518   uint8_t mTextAlign;                   // [inherited] see nsStyleConsts.h
  1519   uint8_t mTextAlignLast;               // [inherited] see nsStyleConsts.h
  1520   bool mTextAlignTrue : 1;              // [inherited] see nsStyleConsts.h
  1521   bool mTextAlignLastTrue : 1;          // [inherited] see nsStyleConsts.h
  1522   uint8_t mTextTransform;               // [inherited] see nsStyleConsts.h
  1523   uint8_t mWhiteSpace;                  // [inherited] see nsStyleConsts.h
  1524   uint8_t mWordBreak;                   // [inherited] see nsStyleConsts.h
  1525   uint8_t mWordWrap;                    // [inherited] see nsStyleConsts.h
  1526   uint8_t mHyphens;                     // [inherited] see nsStyleConsts.h
  1527   uint8_t mTextSizeAdjust;              // [inherited] see nsStyleConsts.h
  1528   uint8_t mTextOrientation;             // [inherited] see nsStyleConsts.h
  1529   uint8_t mTextCombineUpright;          // [inherited] see nsStyleConsts.h
  1530   uint8_t mControlCharacterVisibility;  // [inherited] see nsStyleConsts.h
  1531   int32_t mTabSize;                     // [inherited] see nsStyleConsts.h
  1533   nscoord mWordSpacing;                 // [inherited]
  1534   nsStyleCoord  mLetterSpacing;         // [inherited] coord, normal
  1535   nsStyleCoord  mLineHeight;            // [inherited] coord, factor, normal
  1536   nsStyleCoord  mTextIndent;            // [inherited] coord, percent, calc
  1538   nsRefPtr<nsCSSShadowArray> mTextShadow; // [inherited] nullptr in case of a zero-length
  1540   bool WhiteSpaceIsSignificant() const {
  1541     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
  1542            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
  1543            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
  1546   bool NewlineIsSignificant() const {
  1547     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
  1548            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
  1549            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
  1552   bool NewlineIsDiscarded() const {
  1553     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
  1556   bool WhiteSpaceOrNewlineIsSignificant() const {
  1557     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
  1558            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
  1559            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
  1560            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
  1563   bool WhiteSpaceCanWrapStyle() const {
  1564     return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
  1565            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
  1566            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
  1569   bool WordCanWrapStyle() const {
  1570     return WhiteSpaceCanWrapStyle() &&
  1571            mWordWrap == NS_STYLE_WORDWRAP_BREAK_WORD;
  1574   // These are defined in nsStyleStructInlines.h.
  1575   inline bool HasTextShadow() const;
  1576   inline nsCSSShadowArray* GetTextShadow() const;
  1578   // The aContextFrame argument on each of these is the frame this
  1579   // style struct is for.  If the frame is for SVG text, the return
  1580   // value will be massaged to be something that makes sense for
  1581   // SVG text.
  1582   inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
  1583   inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
  1584 };
  1586 struct nsStyleImageOrientation {
  1587   static nsStyleImageOrientation CreateAsAngleAndFlip(double aRadians,
  1588                                                       bool aFlip) {
  1589     uint8_t orientation(0);
  1591     // Compute the final angle value, rounding to the closest quarter turn.
  1592     double roundedAngle = fmod(aRadians, 2 * M_PI);
  1593     if      (roundedAngle < 0.25 * M_PI) orientation = ANGLE_0;
  1594     else if (roundedAngle < 0.75 * M_PI) orientation = ANGLE_90;
  1595     else if (roundedAngle < 1.25 * M_PI) orientation = ANGLE_180;
  1596     else if (roundedAngle < 1.75 * M_PI) orientation = ANGLE_270;
  1597     else                                 orientation = ANGLE_0;
  1599     // Add a bit for 'flip' if needed.
  1600     if (aFlip)
  1601       orientation |= FLIP_MASK;
  1603     return nsStyleImageOrientation(orientation);
  1606   static nsStyleImageOrientation CreateAsFlip() {
  1607     return nsStyleImageOrientation(FLIP_MASK);
  1610   static nsStyleImageOrientation CreateAsFromImage() {
  1611     return nsStyleImageOrientation(FROM_IMAGE_MASK);
  1614   // The default constructor yields 0 degrees of rotation and no flip.
  1615   nsStyleImageOrientation() : mOrientation(0) { }
  1617   bool IsDefault()   const { return mOrientation == 0; }
  1618   bool IsFlipped()   const { return mOrientation & FLIP_MASK; }
  1619   bool IsFromImage() const { return mOrientation & FROM_IMAGE_MASK; }
  1621   mozilla::image::Angle Angle() const {
  1622     switch (mOrientation & ORIENTATION_MASK) {
  1623       case ANGLE_0:   return mozilla::image::Angle::D0;
  1624       case ANGLE_90:  return mozilla::image::Angle::D90;
  1625       case ANGLE_180: return mozilla::image::Angle::D180;
  1626       case ANGLE_270: return mozilla::image::Angle::D270;
  1627       default:
  1628         NS_NOTREACHED("Unexpected angle");
  1629         return mozilla::image::Angle::D0;
  1633   nsStyleCoord AngleAsCoord() const {
  1634     switch (mOrientation & ORIENTATION_MASK) {
  1635       case ANGLE_0:   return nsStyleCoord(0.0f,   eStyleUnit_Degree);
  1636       case ANGLE_90:  return nsStyleCoord(90.0f,  eStyleUnit_Degree);
  1637       case ANGLE_180: return nsStyleCoord(180.0f, eStyleUnit_Degree);
  1638       case ANGLE_270: return nsStyleCoord(270.0f, eStyleUnit_Degree);
  1639       default:
  1640         NS_NOTREACHED("Unexpected angle");
  1641         return nsStyleCoord();
  1645   bool operator==(const nsStyleImageOrientation& aOther) const {
  1646     return aOther.mOrientation == mOrientation;
  1649   bool operator!=(const nsStyleImageOrientation& aOther) const {
  1650     return !(*this == aOther);
  1653 protected:
  1654   enum Bits {
  1655     ORIENTATION_MASK = 0x1 | 0x2,  // The bottom two bits are the angle.
  1656     FLIP_MASK        = 0x4,        // Whether the image should be flipped.
  1657     FROM_IMAGE_MASK  = 0x8,        // Whether the image's inherent orientation
  1658   };                               // should be used.
  1660   enum Angles {
  1661     ANGLE_0   = 0,
  1662     ANGLE_90  = 1,
  1663     ANGLE_180 = 2,
  1664     ANGLE_270 = 3,
  1665   };
  1667   explicit nsStyleImageOrientation(uint8_t aOrientation)
  1668     : mOrientation(aOrientation)
  1669   { }
  1671   uint8_t mOrientation;
  1672 };
  1674 struct nsStyleVisibility {
  1675   nsStyleVisibility(nsPresContext* aPresContext);
  1676   nsStyleVisibility(const nsStyleVisibility& aVisibility);
  1677   ~nsStyleVisibility() {
  1678     MOZ_COUNT_DTOR(nsStyleVisibility);
  1681   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1682     return aContext->AllocateFromShell(sz);
  1684   void Destroy(nsPresContext* aContext) {
  1685     this->~nsStyleVisibility();
  1686     aContext->FreeToShell(sizeof(nsStyleVisibility), this);
  1689   nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const;
  1690   static nsChangeHint MaxDifference() {
  1691     return NS_STYLE_HINT_FRAMECHANGE;
  1693   static nsChangeHint MaxDifferenceNeverInherited() {
  1694     // CalcDifference never returns nsChangeHint_NeedReflow or
  1695     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  1696     return NS_CombineHint(nsChangeHint_NeedReflow,
  1697                           nsChangeHint_ClearAncestorIntrinsics);
  1700   nsStyleImageOrientation mImageOrientation;  // [inherited]
  1701   uint8_t mDirection;                  // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
  1702   uint8_t mVisible;                    // [inherited]
  1703   uint8_t mPointerEvents;              // [inherited] see nsStyleConsts.h
  1704   uint8_t mWritingMode;                // [inherited] see nsStyleConsts.h
  1706   bool IsVisible() const {
  1707     return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
  1710   bool IsVisibleOrCollapsed() const {
  1711     return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
  1712             (mVisible == NS_STYLE_VISIBILITY_COLLAPSE));
  1715   inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
  1716 };
  1718 struct nsTimingFunction {
  1719   enum Type { Function, StepStart, StepEnd };
  1721   explicit nsTimingFunction(int32_t aTimingFunctionType
  1722                               = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)
  1724     AssignFromKeyword(aTimingFunctionType);
  1727   nsTimingFunction(float x1, float y1, float x2, float y2)
  1728     : mType(Function)
  1730     mFunc.mX1 = x1;
  1731     mFunc.mY1 = y1;
  1732     mFunc.mX2 = x2;
  1733     mFunc.mY2 = y2;
  1736   nsTimingFunction(Type aType, uint32_t aSteps)
  1737     : mType(aType)
  1739     NS_ABORT_IF_FALSE(mType == StepStart || mType == StepEnd, "wrong type");
  1740     mSteps = aSteps;
  1743   nsTimingFunction(const nsTimingFunction& aOther)
  1745     *this = aOther;
  1748   Type mType;
  1749   union {
  1750     struct {
  1751       float mX1;
  1752       float mY1;
  1753       float mX2;
  1754       float mY2;
  1755     } mFunc;
  1756     uint32_t mSteps;
  1757   };
  1759   nsTimingFunction&
  1760   operator=(const nsTimingFunction& aOther)
  1762     if (&aOther == this)
  1763       return *this;
  1765     mType = aOther.mType;
  1767     if (mType == Function) {
  1768       mFunc.mX1 = aOther.mFunc.mX1;
  1769       mFunc.mY1 = aOther.mFunc.mY1;
  1770       mFunc.mX2 = aOther.mFunc.mX2;
  1771       mFunc.mY2 = aOther.mFunc.mY2;
  1772     } else {
  1773       mSteps = aOther.mSteps;
  1776     return *this;
  1779   bool operator==(const nsTimingFunction& aOther) const
  1781     if (mType != aOther.mType) {
  1782       return false;
  1784     if (mType == Function) {
  1785       return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
  1786              mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
  1788     return mSteps == aOther.mSteps;
  1791   bool operator!=(const nsTimingFunction& aOther) const
  1793     return !(*this == aOther);
  1796 private:
  1797   void AssignFromKeyword(int32_t aTimingFunctionType);
  1798 };
  1800 struct nsTransition {
  1801   nsTransition() { /* leaves uninitialized; see also SetInitialValues */ }
  1802   explicit nsTransition(const nsTransition& aCopy);
  1804   void SetInitialValues();
  1806   // Delay and Duration are in milliseconds
  1808   const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
  1809   float GetDelay() const { return mDelay; }
  1810   float GetDuration() const { return mDuration; }
  1811   nsCSSProperty GetProperty() const { return mProperty; }
  1812   nsIAtom* GetUnknownProperty() const { return mUnknownProperty; }
  1814   void SetTimingFunction(const nsTimingFunction& aTimingFunction)
  1815     { mTimingFunction = aTimingFunction; }
  1816   void SetDelay(float aDelay) { mDelay = aDelay; }
  1817   void SetDuration(float aDuration) { mDuration = aDuration; }
  1818   void SetProperty(nsCSSProperty aProperty)
  1820       NS_ASSERTION(aProperty != eCSSProperty_UNKNOWN, "invalid property");
  1821       mProperty = aProperty;
  1823   void SetUnknownProperty(const nsAString& aUnknownProperty);
  1824   void CopyPropertyFrom(const nsTransition& aOther)
  1826       mProperty = aOther.mProperty;
  1827       mUnknownProperty = aOther.mUnknownProperty;
  1830   nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
  1832 private:
  1833   nsTimingFunction mTimingFunction;
  1834   float mDuration;
  1835   float mDelay;
  1836   nsCSSProperty mProperty;
  1837   nsCOMPtr<nsIAtom> mUnknownProperty; // used when mProperty is
  1838                                       // eCSSProperty_UNKNOWN
  1839 };
  1841 struct nsAnimation {
  1842   nsAnimation() { /* leaves uninitialized; see also SetInitialValues */ }
  1843   explicit nsAnimation(const nsAnimation& aCopy);
  1845   void SetInitialValues();
  1847   // Delay and Duration are in milliseconds
  1849   const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
  1850   float GetDelay() const { return mDelay; }
  1851   float GetDuration() const { return mDuration; }
  1852   const nsString& GetName() const { return mName; }
  1853   uint8_t GetDirection() const { return mDirection; }
  1854   uint8_t GetFillMode() const { return mFillMode; }
  1855   uint8_t GetPlayState() const { return mPlayState; }
  1856   float GetIterationCount() const { return mIterationCount; }
  1858   void SetTimingFunction(const nsTimingFunction& aTimingFunction)
  1859     { mTimingFunction = aTimingFunction; }
  1860   void SetDelay(float aDelay) { mDelay = aDelay; }
  1861   void SetDuration(float aDuration) { mDuration = aDuration; }
  1862   void SetName(const nsSubstring& aName) { mName = aName; }
  1863   void SetDirection(uint8_t aDirection) { mDirection = aDirection; }
  1864   void SetFillMode(uint8_t aFillMode) { mFillMode = aFillMode; }
  1865   void SetPlayState(uint8_t aPlayState) { mPlayState = aPlayState; }
  1866   void SetIterationCount(float aIterationCount)
  1867     { mIterationCount = aIterationCount; }
  1869   nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
  1871 private:
  1872   nsTimingFunction mTimingFunction;
  1873   float mDuration;
  1874   float mDelay;
  1875   nsString mName; // empty string for 'none'
  1876   uint8_t mDirection;
  1877   uint8_t mFillMode;
  1878   uint8_t mPlayState;
  1879   float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
  1880 };
  1882 struct nsStyleDisplay {
  1883   nsStyleDisplay();
  1884   nsStyleDisplay(const nsStyleDisplay& aOther);
  1885   ~nsStyleDisplay() {
  1886     MOZ_COUNT_DTOR(nsStyleDisplay);
  1889   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  1890     return aContext->AllocateFromShell(sz);
  1892   void Destroy(nsPresContext* aContext) {
  1893     this->~nsStyleDisplay();
  1894     aContext->FreeToShell(sizeof(nsStyleDisplay), this);
  1897   nsChangeHint CalcDifference(const nsStyleDisplay& aOther) const;
  1898   static nsChangeHint MaxDifference() {
  1899     // All the parts of FRAMECHANGE are present in CalcDifference.
  1900     return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
  1901                         nsChangeHint_UpdateOpacityLayer |
  1902                         nsChangeHint_UpdateTransformLayer |
  1903                         nsChangeHint_UpdateOverflow |
  1904                         nsChangeHint_UpdatePostTransformOverflow |
  1905                         nsChangeHint_AddOrRemoveTransform);
  1907   static nsChangeHint MaxDifferenceNeverInherited() {
  1908     // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
  1909     // nsChangeHint_NeedReflow as inherited hints.
  1910     return nsChangeHint(0);
  1913   // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
  1914   // mBinding->mOriginPrincipal.
  1915   nsRefPtr<mozilla::css::URLValue> mBinding;    // [reset]
  1916   nsRect  mClip;                // [reset] offsets from upper-left border edge
  1917   float   mOpacity;             // [reset]
  1918   uint8_t mDisplay;             // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
  1919   uint8_t mOriginalDisplay;     // [reset] saved mDisplay for position:absolute/fixed
  1920                                 //         and float:left/right; otherwise equal
  1921                                 //         to mDisplay
  1922   uint8_t mAppearance;          // [reset]
  1923   uint8_t mPosition;            // [reset] see nsStyleConsts.h
  1924   uint8_t mFloats;              // [reset] see nsStyleConsts.h NS_STYLE_FLOAT_*
  1925   uint8_t mOriginalFloats;      // [reset] saved mFloats for position:absolute/fixed;
  1926                                 //         otherwise equal to mFloats
  1927   uint8_t mBreakType;           // [reset] see nsStyleConsts.h NS_STYLE_CLEAR_*
  1928   uint8_t mBreakInside;         // [reset] NS_STYLE_PAGE_BREAK_AUTO/AVOID
  1929   bool mBreakBefore;    // [reset]
  1930   bool mBreakAfter;     // [reset]
  1931   uint8_t mOverflowX;           // [reset] see nsStyleConsts.h
  1932   uint8_t mOverflowY;           // [reset] see nsStyleConsts.h
  1933   uint8_t mOverflowClipBox;     // [reset] see nsStyleConsts.h
  1934   uint8_t mResize;              // [reset] see nsStyleConsts.h
  1935   uint8_t mClipFlags;           // [reset] see nsStyleConsts.h
  1936   uint8_t mOrient;              // [reset] see nsStyleConsts.h
  1937   uint8_t mMixBlendMode;        // [reset] see nsStyleConsts.h
  1938   uint8_t mWillChangeBitField;  // [reset] see nsStyleConsts.h. Stores a
  1939                                 // bitfield representation of the properties
  1940                                 // that are frequently queried. This should
  1941                                 // match mWillChange. Also tracks if any of the
  1942                                 // properties in the will-change list require
  1943                                 // a stacking context.
  1944   nsAutoTArray<nsString, 1> mWillChange;
  1946   uint8_t mTouchAction;         // [reset] see nsStyleConsts.h
  1948   // mSpecifiedTransform is the list of transform functions as
  1949   // specified, or null to indicate there is no transform.  (inherit or
  1950   // initial are replaced by an actual list of transform functions, or
  1951   // null, as appropriate.)
  1952   uint8_t mBackfaceVisibility;
  1953   uint8_t mTransformStyle;
  1954   nsRefPtr<nsCSSValueSharedList> mSpecifiedTransform; // [reset]
  1955   nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
  1956   nsStyleCoord mChildPerspective; // [reset] coord
  1957   nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
  1959   nsAutoTArray<nsTransition, 1> mTransitions; // [reset]
  1960   // The number of elements in mTransitions that are not from repeating
  1961   // a list due to another property being longer.
  1962   uint32_t mTransitionTimingFunctionCount,
  1963            mTransitionDurationCount,
  1964            mTransitionDelayCount,
  1965            mTransitionPropertyCount;
  1967   nsAutoTArray<nsAnimation, 1> mAnimations; // [reset]
  1968   // The number of elements in mAnimations that are not from repeating
  1969   // a list due to another property being longer.
  1970   uint32_t mAnimationTimingFunctionCount,
  1971            mAnimationDurationCount,
  1972            mAnimationDelayCount,
  1973            mAnimationNameCount,
  1974            mAnimationDirectionCount,
  1975            mAnimationFillModeCount,
  1976            mAnimationPlayStateCount,
  1977            mAnimationIterationCountCount;
  1979   bool IsBlockInsideStyle() const {
  1980     return NS_STYLE_DISPLAY_BLOCK == mDisplay ||
  1981            NS_STYLE_DISPLAY_LIST_ITEM == mDisplay ||
  1982            NS_STYLE_DISPLAY_INLINE_BLOCK == mDisplay;
  1983     // Should TABLE_CELL and TABLE_CAPTION go here?  They have
  1984     // block frames nested inside of them.
  1985     // (But please audit all callers before changing.)
  1988   bool IsBlockOutsideStyle() const {
  1989     return NS_STYLE_DISPLAY_BLOCK == mDisplay ||
  1990            NS_STYLE_DISPLAY_FLEX == mDisplay ||
  1991            NS_STYLE_DISPLAY_GRID == mDisplay ||
  1992            NS_STYLE_DISPLAY_LIST_ITEM == mDisplay ||
  1993            NS_STYLE_DISPLAY_TABLE == mDisplay;
  1996   static bool IsDisplayTypeInlineOutside(uint8_t aDisplay) {
  1997     return NS_STYLE_DISPLAY_INLINE == aDisplay ||
  1998            NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay ||
  1999            NS_STYLE_DISPLAY_INLINE_TABLE == aDisplay ||
  2000            NS_STYLE_DISPLAY_INLINE_BOX == aDisplay ||
  2001            NS_STYLE_DISPLAY_INLINE_FLEX == aDisplay ||
  2002            NS_STYLE_DISPLAY_INLINE_GRID == aDisplay ||
  2003            NS_STYLE_DISPLAY_INLINE_XUL_GRID == aDisplay ||
  2004            NS_STYLE_DISPLAY_INLINE_STACK == aDisplay;
  2007   bool IsInlineOutsideStyle() const {
  2008     return IsDisplayTypeInlineOutside(mDisplay);
  2011   bool IsOriginalDisplayInlineOutsideStyle() const {
  2012     return IsDisplayTypeInlineOutside(mOriginalDisplay);
  2015   bool IsInnerTableStyle() const {
  2016     return NS_STYLE_DISPLAY_TABLE_CAPTION == mDisplay ||
  2017            NS_STYLE_DISPLAY_TABLE_CELL == mDisplay ||
  2018            NS_STYLE_DISPLAY_TABLE_ROW == mDisplay ||
  2019            NS_STYLE_DISPLAY_TABLE_ROW_GROUP == mDisplay ||
  2020            NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == mDisplay ||
  2021            NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == mDisplay ||
  2022            NS_STYLE_DISPLAY_TABLE_COLUMN == mDisplay ||
  2023            NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == mDisplay;
  2026   bool IsFloatingStyle() const {
  2027     return NS_STYLE_FLOAT_NONE != mFloats;
  2030   bool IsAbsolutelyPositionedStyle() const {
  2031     return NS_STYLE_POSITION_ABSOLUTE == mPosition ||
  2032            NS_STYLE_POSITION_FIXED == mPosition;
  2035   bool IsRelativelyPositionedStyle() const {
  2036     return NS_STYLE_POSITION_RELATIVE == mPosition ||
  2037            NS_STYLE_POSITION_STICKY == mPosition;
  2040   bool IsScrollableOverflow() const {
  2041     // mOverflowX and mOverflowY always match when one of them is
  2042     // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
  2043     return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
  2044            mOverflowX != NS_STYLE_OVERFLOW_CLIP;
  2047   /* Returns whether the element has the -moz-transform property
  2048    * or a related property. */
  2049   bool HasTransformStyle() const {
  2050     return mSpecifiedTransform != nullptr ||
  2051            mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
  2052            (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
  2055   bool HasPerspectiveStyle() const {
  2056     return mChildPerspective.GetUnit() == eStyleUnit_Coord;
  2059   bool BackfaceIsHidden() const {
  2060     return mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
  2063   // These are defined in nsStyleStructInlines.h.
  2065   // The aContextFrame argument on each of these is the frame this
  2066   // style struct is for.  If the frame is for SVG text, the return
  2067   // value will be massaged to be something that makes sense for
  2068   // SVG text.
  2069   inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
  2070   inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
  2071   inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
  2072   inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
  2073   inline uint8_t GetDisplay(const nsIFrame* aContextFrame) const;
  2074   inline bool IsFloating(const nsIFrame* aContextFrame) const;
  2075   inline bool IsPositioned(const nsIFrame* aContextFrame) const;
  2076   inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
  2077   inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
  2079   /* Returns whether the element has the -moz-transform property
  2080    * or a related property, and supports CSS transforms. */
  2081   inline bool HasTransform(const nsIFrame* aContextFrame) const;
  2082 };
  2084 struct nsStyleTable {
  2085   nsStyleTable(void);
  2086   nsStyleTable(const nsStyleTable& aOther);
  2087   ~nsStyleTable(void);
  2089   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2090     return aContext->AllocateFromShell(sz);
  2092   void Destroy(nsPresContext* aContext) {
  2093     this->~nsStyleTable();
  2094     aContext->FreeToShell(sizeof(nsStyleTable), this);
  2097   nsChangeHint CalcDifference(const nsStyleTable& aOther) const;
  2098   static nsChangeHint MaxDifference() {
  2099     return NS_STYLE_HINT_FRAMECHANGE;
  2101   static nsChangeHint MaxDifferenceNeverInherited() {
  2102     // CalcDifference never returns nsChangeHint_NeedReflow or
  2103     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2104     return NS_CombineHint(nsChangeHint_NeedReflow,
  2105                           nsChangeHint_ClearAncestorIntrinsics);
  2108   uint8_t       mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
  2109   uint8_t       mFrame;         // [reset] see nsStyleConsts.h NS_STYLE_TABLE_FRAME_*
  2110   uint8_t       mRules;         // [reset] see nsStyleConsts.h NS_STYLE_TABLE_RULES_*
  2111   int32_t       mSpan;          // [reset] the number of columns spanned by a colgroup or col
  2112 };
  2114 struct nsStyleTableBorder {
  2115   nsStyleTableBorder(nsPresContext* aContext);
  2116   nsStyleTableBorder(const nsStyleTableBorder& aOther);
  2117   ~nsStyleTableBorder(void);
  2119   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2120     return aContext->AllocateFromShell(sz);
  2122   void Destroy(nsPresContext* aContext) {
  2123     this->~nsStyleTableBorder();
  2124     aContext->FreeToShell(sizeof(nsStyleTableBorder), this);
  2127   nsChangeHint CalcDifference(const nsStyleTableBorder& aOther) const;
  2128   static nsChangeHint MaxDifference() {
  2129     return NS_STYLE_HINT_FRAMECHANGE;
  2131   static nsChangeHint MaxDifferenceNeverInherited() {
  2132     // CalcDifference never returns nsChangeHint_NeedReflow or
  2133     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2134     return NS_CombineHint(nsChangeHint_NeedReflow,
  2135                           nsChangeHint_ClearAncestorIntrinsics);
  2138   nscoord       mBorderSpacingX;// [inherited]
  2139   nscoord       mBorderSpacingY;// [inherited]
  2140   uint8_t       mBorderCollapse;// [inherited]
  2141   uint8_t       mCaptionSide;   // [inherited]
  2142   uint8_t       mEmptyCells;    // [inherited]
  2143 };
  2145 enum nsStyleContentType {
  2146   eStyleContentType_String        = 1,
  2147   eStyleContentType_Image         = 10,
  2148   eStyleContentType_Attr          = 20,
  2149   eStyleContentType_Counter       = 30,
  2150   eStyleContentType_Counters      = 31,
  2151   eStyleContentType_OpenQuote     = 40,
  2152   eStyleContentType_CloseQuote    = 41,
  2153   eStyleContentType_NoOpenQuote   = 42,
  2154   eStyleContentType_NoCloseQuote  = 43,
  2155   eStyleContentType_AltContent    = 50,
  2156   eStyleContentType_Uninitialized
  2157 };
  2159 struct nsStyleContentData {
  2160   nsStyleContentType  mType;
  2161   union {
  2162     char16_t *mString;
  2163     imgRequestProxy *mImage;
  2164     nsCSSValue::Array* mCounters;
  2165   } mContent;
  2166 #ifdef DEBUG
  2167   bool mImageTracked;
  2168 #endif
  2170   nsStyleContentData()
  2171     : mType(eStyleContentType_Uninitialized)
  2172 #ifdef DEBUG
  2173     , mImageTracked(false)
  2174 #endif
  2175   { mContent.mString = nullptr; }
  2177   ~nsStyleContentData();
  2178   nsStyleContentData& operator=(const nsStyleContentData& aOther);
  2179   bool operator==(const nsStyleContentData& aOther) const;
  2181   bool operator!=(const nsStyleContentData& aOther) const {
  2182     return !(*this == aOther);
  2185   void TrackImage(nsPresContext* aContext);
  2186   void UntrackImage(nsPresContext* aContext);
  2188   void SetImage(imgRequestProxy* aRequest)
  2190     NS_ABORT_IF_FALSE(!mImageTracked,
  2191                       "Setting a new image without untracking the old one!");
  2192     NS_ABORT_IF_FALSE(mType == eStyleContentType_Image, "Wrong type!");
  2193     NS_IF_ADDREF(mContent.mImage = aRequest);
  2195 private:
  2196   nsStyleContentData(const nsStyleContentData&); // not to be implemented
  2197 };
  2199 struct nsStyleCounterData {
  2200   nsString  mCounter;
  2201   int32_t   mValue;
  2202 };
  2205 #define DELETE_ARRAY_IF(array)  if (array) { delete[] array; array = nullptr; }
  2207 struct nsStyleQuotes {
  2208   nsStyleQuotes();
  2209   nsStyleQuotes(const nsStyleQuotes& aQuotes);
  2210   ~nsStyleQuotes();
  2212   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2213     return aContext->AllocateFromShell(sz);
  2215   void Destroy(nsPresContext* aContext) {
  2216     this->~nsStyleQuotes();
  2217     aContext->FreeToShell(sizeof(nsStyleQuotes), this);
  2220   void SetInitial();
  2221   void CopyFrom(const nsStyleQuotes& aSource);
  2223   nsChangeHint CalcDifference(const nsStyleQuotes& aOther) const;
  2224   static nsChangeHint MaxDifference() {
  2225     return NS_STYLE_HINT_FRAMECHANGE;
  2227   static nsChangeHint MaxDifferenceNeverInherited() {
  2228     // CalcDifference never returns nsChangeHint_NeedReflow or
  2229     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2230     return NS_CombineHint(nsChangeHint_NeedReflow,
  2231                           nsChangeHint_ClearAncestorIntrinsics);
  2234   uint32_t  QuotesCount(void) const { return mQuotesCount; } // [inherited]
  2236   const nsString* OpenQuoteAt(uint32_t aIndex) const
  2238     NS_ASSERTION(aIndex < mQuotesCount, "out of range");
  2239     return mQuotes + (aIndex * 2);
  2241   const nsString* CloseQuoteAt(uint32_t aIndex) const
  2243     NS_ASSERTION(aIndex < mQuotesCount, "out of range");
  2244     return mQuotes + (aIndex * 2 + 1);
  2246   nsresult  GetQuotesAt(uint32_t aIndex, nsString& aOpen, nsString& aClose) const {
  2247     if (aIndex < mQuotesCount) {
  2248       aIndex *= 2;
  2249       aOpen = mQuotes[aIndex];
  2250       aClose = mQuotes[++aIndex];
  2251       return NS_OK;
  2253     return NS_ERROR_ILLEGAL_VALUE;
  2256   nsresult  AllocateQuotes(uint32_t aCount) {
  2257     if (aCount != mQuotesCount) {
  2258       DELETE_ARRAY_IF(mQuotes);
  2259       if (aCount) {
  2260         mQuotes = new nsString[aCount * 2];
  2261         if (! mQuotes) {
  2262           mQuotesCount = 0;
  2263           return NS_ERROR_OUT_OF_MEMORY;
  2266       mQuotesCount = aCount;
  2268     return NS_OK;
  2271   nsresult  SetQuotesAt(uint32_t aIndex, const nsString& aOpen, const nsString& aClose) {
  2272     if (aIndex < mQuotesCount) {
  2273       aIndex *= 2;
  2274       mQuotes[aIndex] = aOpen;
  2275       mQuotes[++aIndex] = aClose;
  2276       return NS_OK;
  2278     return NS_ERROR_ILLEGAL_VALUE;
  2281 protected:
  2282   uint32_t            mQuotesCount;
  2283   nsString*           mQuotes;
  2284 };
  2286 struct nsStyleContent {
  2287   nsStyleContent(void);
  2288   nsStyleContent(const nsStyleContent& aContent);
  2289   ~nsStyleContent(void);
  2291   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2292     return aContext->AllocateFromShell(sz);
  2294   void Destroy(nsPresContext* aContext);
  2296   nsChangeHint CalcDifference(const nsStyleContent& aOther) const;
  2297   static nsChangeHint MaxDifference() {
  2298     return NS_STYLE_HINT_FRAMECHANGE;
  2300   static nsChangeHint MaxDifferenceNeverInherited() {
  2301     // CalcDifference never returns nsChangeHint_NeedReflow or
  2302     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2303     return NS_CombineHint(nsChangeHint_NeedReflow,
  2304                           nsChangeHint_ClearAncestorIntrinsics);
  2307   uint32_t  ContentCount(void) const  { return mContentCount; } // [reset]
  2309   const nsStyleContentData& ContentAt(uint32_t aIndex) const {
  2310     NS_ASSERTION(aIndex < mContentCount, "out of range");
  2311     return mContents[aIndex];
  2314   nsStyleContentData& ContentAt(uint32_t aIndex) {
  2315     NS_ASSERTION(aIndex < mContentCount, "out of range");
  2316     return mContents[aIndex];
  2319   nsresult AllocateContents(uint32_t aCount);
  2321   uint32_t  CounterIncrementCount(void) const { return mIncrementCount; }  // [reset]
  2322   const nsStyleCounterData* GetCounterIncrementAt(uint32_t aIndex) const {
  2323     NS_ASSERTION(aIndex < mIncrementCount, "out of range");
  2324     return &mIncrements[aIndex];
  2327   nsresult  AllocateCounterIncrements(uint32_t aCount) {
  2328     if (aCount != mIncrementCount) {
  2329       DELETE_ARRAY_IF(mIncrements);
  2330       if (aCount) {
  2331         mIncrements = new nsStyleCounterData[aCount];
  2332         if (! mIncrements) {
  2333           mIncrementCount = 0;
  2334           return NS_ERROR_OUT_OF_MEMORY;
  2337       mIncrementCount = aCount;
  2339     return NS_OK;
  2342   nsresult  SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
  2343     if (aIndex < mIncrementCount) {
  2344       mIncrements[aIndex].mCounter = aCounter;
  2345       mIncrements[aIndex].mValue = aIncrement;
  2346       return NS_OK;
  2348     return NS_ERROR_ILLEGAL_VALUE;
  2351   uint32_t  CounterResetCount(void) const { return mResetCount; }  // [reset]
  2352   const nsStyleCounterData* GetCounterResetAt(uint32_t aIndex) const {
  2353     NS_ASSERTION(aIndex < mResetCount, "out of range");
  2354     return &mResets[aIndex];
  2357   nsresult  AllocateCounterResets(uint32_t aCount) {
  2358     if (aCount != mResetCount) {
  2359       DELETE_ARRAY_IF(mResets);
  2360       if (aCount) {
  2361         mResets = new nsStyleCounterData[aCount];
  2362         if (! mResets) {
  2363           mResetCount = 0;
  2364           return NS_ERROR_OUT_OF_MEMORY;
  2367       mResetCount = aCount;
  2369     return NS_OK;
  2372   nsresult  SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
  2373     if (aIndex < mResetCount) {
  2374       mResets[aIndex].mCounter = aCounter;
  2375       mResets[aIndex].mValue = aValue;
  2376       return NS_OK;
  2378     return NS_ERROR_ILLEGAL_VALUE;
  2381   nsStyleCoord  mMarkerOffset;  // [reset] coord, auto
  2383 protected:
  2384   nsStyleContentData* mContents;
  2385   nsStyleCounterData* mIncrements;
  2386   nsStyleCounterData* mResets;
  2388   uint32_t            mContentCount;
  2389   uint32_t            mIncrementCount;
  2390   uint32_t            mResetCount;
  2391 };
  2393 struct nsStyleUIReset {
  2394   nsStyleUIReset(void);
  2395   nsStyleUIReset(const nsStyleUIReset& aOther);
  2396   ~nsStyleUIReset(void);
  2398   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2399     return aContext->AllocateFromShell(sz);
  2401   void Destroy(nsPresContext* aContext) {
  2402     this->~nsStyleUIReset();
  2403     aContext->FreeToShell(sizeof(nsStyleUIReset), this);
  2406   nsChangeHint CalcDifference(const nsStyleUIReset& aOther) const;
  2407   static nsChangeHint MaxDifference() {
  2408     return NS_STYLE_HINT_FRAMECHANGE;
  2410   static nsChangeHint MaxDifferenceNeverInherited() {
  2411     // CalcDifference never returns nsChangeHint_NeedReflow or
  2412     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2413     return NS_CombineHint(nsChangeHint_NeedReflow,
  2414                           nsChangeHint_ClearAncestorIntrinsics);
  2417   uint8_t   mUserSelect;      // [reset] (selection-style)
  2418   uint8_t   mForceBrokenImageIcon; // [reset]  (0 if not forcing, otherwise forcing)
  2419   uint8_t   mIMEMode;         // [reset]
  2420   uint8_t   mWindowShadow;    // [reset]
  2421 };
  2423 struct nsCursorImage {
  2424   bool mHaveHotspot;
  2425   float mHotspotX, mHotspotY;
  2427   nsCursorImage();
  2428   nsCursorImage(const nsCursorImage& aOther);
  2429   ~nsCursorImage();
  2431   nsCursorImage& operator=(const nsCursorImage& aOther);
  2432   /*
  2433    * We hide mImage and force access through the getter and setter so that we
  2434    * can lock the images we use. Cursor images are likely to be small, so we
  2435    * don't care about discarding them. See bug 512260.
  2436    * */
  2437   void SetImage(imgIRequest *aImage) {
  2438     if (mImage)
  2439       mImage->UnlockImage();
  2440     mImage = aImage;
  2441     if (mImage)
  2442       mImage->LockImage();
  2444   imgIRequest* GetImage() const {
  2445     return mImage;
  2448 private:
  2449   nsCOMPtr<imgIRequest> mImage;
  2450 };
  2452 struct nsStyleUserInterface {
  2453   nsStyleUserInterface(void);
  2454   nsStyleUserInterface(const nsStyleUserInterface& aOther);
  2455   ~nsStyleUserInterface(void);
  2457   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2458     return aContext->AllocateFromShell(sz);
  2460   void Destroy(nsPresContext* aContext) {
  2461     this->~nsStyleUserInterface();
  2462     aContext->FreeToShell(sizeof(nsStyleUserInterface), this);
  2465   nsChangeHint CalcDifference(const nsStyleUserInterface& aOther) const;
  2466   static nsChangeHint MaxDifference() {
  2467     return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
  2469   static nsChangeHint MaxDifferenceNeverInherited() {
  2470     // CalcDifference never returns nsChangeHint_NeedReflow or
  2471     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2472     return NS_CombineHint(nsChangeHint_NeedReflow,
  2473                           nsChangeHint_ClearAncestorIntrinsics);
  2476   uint8_t   mUserInput;       // [inherited]
  2477   uint8_t   mUserModify;      // [inherited] (modify-content)
  2478   uint8_t   mUserFocus;       // [inherited] (auto-select)
  2480   uint8_t   mCursor;          // [inherited] See nsStyleConsts.h
  2482   uint32_t mCursorArrayLength;
  2483   nsCursorImage *mCursorArray;// [inherited] The specified URL values
  2484                               //   and coordinates.  Takes precedence over
  2485                               //   mCursor.  Zero-length array is represented
  2486                               //   by null pointer.
  2488   // Does not free mCursorArray; the caller is responsible for calling
  2489   // |delete [] mCursorArray| first if it is needed.
  2490   void CopyCursorArrayFrom(const nsStyleUserInterface& aSource);
  2491 };
  2493 struct nsStyleXUL {
  2494   nsStyleXUL();
  2495   nsStyleXUL(const nsStyleXUL& aSource);
  2496   ~nsStyleXUL();
  2498   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2499     return aContext->AllocateFromShell(sz);
  2501   void Destroy(nsPresContext* aContext) {
  2502     this->~nsStyleXUL();
  2503     aContext->FreeToShell(sizeof(nsStyleXUL), this);
  2506   nsChangeHint CalcDifference(const nsStyleXUL& aOther) const;
  2507   static nsChangeHint MaxDifference() {
  2508     return NS_STYLE_HINT_FRAMECHANGE;
  2510   static nsChangeHint MaxDifferenceNeverInherited() {
  2511     // CalcDifference never returns nsChangeHint_NeedReflow or
  2512     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2513     return NS_CombineHint(nsChangeHint_NeedReflow,
  2514                           nsChangeHint_ClearAncestorIntrinsics);
  2517   float         mBoxFlex;               // [reset] see nsStyleConsts.h
  2518   uint32_t      mBoxOrdinal;            // [reset] see nsStyleConsts.h
  2519   uint8_t       mBoxAlign;              // [reset] see nsStyleConsts.h
  2520   uint8_t       mBoxDirection;          // [reset] see nsStyleConsts.h
  2521   uint8_t       mBoxOrient;             // [reset] see nsStyleConsts.h
  2522   uint8_t       mBoxPack;               // [reset] see nsStyleConsts.h
  2523   bool          mStretchStack;          // [reset] see nsStyleConsts.h
  2524 };
  2526 struct nsStyleColumn {
  2527   nsStyleColumn(nsPresContext* aPresContext);
  2528   nsStyleColumn(const nsStyleColumn& aSource);
  2529   ~nsStyleColumn();
  2531   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2532     return aContext->AllocateFromShell(sz);
  2534   void Destroy(nsPresContext* aContext) {
  2535     this->~nsStyleColumn();
  2536     aContext->FreeToShell(sizeof(nsStyleColumn), this);
  2539   nsChangeHint CalcDifference(const nsStyleColumn& aOther) const;
  2540   static nsChangeHint MaxDifference() {
  2541     return NS_STYLE_HINT_FRAMECHANGE;
  2543   static nsChangeHint MaxDifferenceNeverInherited() {
  2544     // CalcDifference never returns nsChangeHint_NeedReflow or
  2545     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2546     return NS_CombineHint(nsChangeHint_NeedReflow,
  2547                           nsChangeHint_ClearAncestorIntrinsics);
  2550   /**
  2551    * This is the maximum number of columns we can process. It's used in both
  2552    * nsColumnSetFrame and nsRuleNode.
  2553    */
  2554   static const uint32_t kMaxColumnCount;
  2556   uint32_t     mColumnCount; // [reset] see nsStyleConsts.h
  2557   nsStyleCoord mColumnWidth; // [reset] coord, auto
  2558   nsStyleCoord mColumnGap;   // [reset] coord, normal
  2560   nscolor      mColumnRuleColor;  // [reset]
  2561   uint8_t      mColumnRuleStyle;  // [reset]
  2562   uint8_t      mColumnFill;  // [reset] see nsStyleConsts.h
  2564   // See https://bugzilla.mozilla.org/show_bug.cgi?id=271586#c43 for why
  2565   // this is hard to replace with 'currentColor'.
  2566   bool mColumnRuleColorIsForeground;
  2568   void SetColumnRuleWidth(nscoord aWidth) {
  2569     mColumnRuleWidth = NS_ROUND_BORDER_TO_PIXELS(aWidth, mTwipsPerPixel);
  2572   nscoord GetComputedColumnRuleWidth() const {
  2573     return (IsVisibleBorderStyle(mColumnRuleStyle) ? mColumnRuleWidth : 0);
  2576 protected:
  2577   nscoord mColumnRuleWidth;  // [reset] coord
  2578   nscoord mTwipsPerPixel;
  2579 };
  2581 enum nsStyleSVGPaintType {
  2582   eStyleSVGPaintType_None = 1,
  2583   eStyleSVGPaintType_Color,
  2584   eStyleSVGPaintType_Server,
  2585   eStyleSVGPaintType_ContextFill,
  2586   eStyleSVGPaintType_ContextStroke
  2587 };
  2589 enum nsStyleSVGOpacitySource {
  2590   eStyleSVGOpacitySource_Normal,
  2591   eStyleSVGOpacitySource_ContextFillOpacity,
  2592   eStyleSVGOpacitySource_ContextStrokeOpacity
  2593 };
  2595 struct nsStyleSVGPaint
  2597   union {
  2598     nscolor mColor;
  2599     nsIURI *mPaintServer;
  2600   } mPaint;
  2601   nsStyleSVGPaintType mType;
  2602   nscolor mFallbackColor;
  2604   nsStyleSVGPaint() : mType(nsStyleSVGPaintType(0)) { mPaint.mPaintServer = nullptr; }
  2605   ~nsStyleSVGPaint();
  2606   void SetType(nsStyleSVGPaintType aType);
  2607   nsStyleSVGPaint& operator=(const nsStyleSVGPaint& aOther);
  2608   bool operator==(const nsStyleSVGPaint& aOther) const;
  2610   bool operator!=(const nsStyleSVGPaint& aOther) const {
  2611     return !(*this == aOther);
  2613 };
  2615 struct nsStyleSVG {
  2616   nsStyleSVG();
  2617   nsStyleSVG(const nsStyleSVG& aSource);
  2618   ~nsStyleSVG();
  2620   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2621     return aContext->AllocateFromShell(sz);
  2623   void Destroy(nsPresContext* aContext) {
  2624     this->~nsStyleSVG();
  2625     aContext->FreeToShell(sizeof(nsStyleSVG), this);
  2628   nsChangeHint CalcDifference(const nsStyleSVG& aOther) const;
  2629   static nsChangeHint MaxDifference() {
  2630     return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
  2631              NS_CombineHint(nsChangeHint_NeedReflow, nsChangeHint_NeedDirtyReflow)), // XXX remove nsChangeHint_NeedDirtyReflow: bug 876085
  2632                                          nsChangeHint_RepaintFrame);
  2634   static nsChangeHint MaxDifferenceNeverInherited() {
  2635     // CalcDifference never returns nsChangeHint_NeedReflow as an inherited hint
  2636     // and never returns nsChangeHint_ClearAncestorIntrinsics at all.
  2637     return nsChangeHint_NeedReflow;
  2640   nsStyleSVGPaint  mFill;             // [inherited]
  2641   nsStyleSVGPaint  mStroke;           // [inherited]
  2642   nsCOMPtr<nsIURI> mMarkerEnd;        // [inherited]
  2643   nsCOMPtr<nsIURI> mMarkerMid;        // [inherited]
  2644   nsCOMPtr<nsIURI> mMarkerStart;      // [inherited]
  2645   nsStyleCoord    *mStrokeDasharray;  // [inherited] coord, percent, factor
  2647   nsStyleCoord     mStrokeDashoffset; // [inherited] coord, percent, factor
  2648   nsStyleCoord     mStrokeWidth;      // [inherited] coord, percent, factor
  2650   float            mFillOpacity;      // [inherited]
  2651   float            mStrokeMiterlimit; // [inherited]
  2652   float            mStrokeOpacity;    // [inherited]
  2654   uint32_t         mStrokeDasharrayLength;
  2655   uint8_t          mClipRule;         // [inherited]
  2656   uint8_t          mColorInterpolation; // [inherited] see nsStyleConsts.h
  2657   uint8_t          mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
  2658   uint8_t          mFillRule;         // [inherited] see nsStyleConsts.h
  2659   uint8_t          mImageRendering;   // [inherited] see nsStyleConsts.h
  2660   uint8_t          mPaintOrder;       // [inherited] see nsStyleConsts.h
  2661   uint8_t          mShapeRendering;   // [inherited] see nsStyleConsts.h
  2662   uint8_t          mStrokeLinecap;    // [inherited] see nsStyleConsts.h
  2663   uint8_t          mStrokeLinejoin;   // [inherited] see nsStyleConsts.h
  2664   uint8_t          mTextAnchor;       // [inherited] see nsStyleConsts.h
  2665   uint8_t          mTextRendering;    // [inherited] see nsStyleConsts.h
  2667   // In SVG glyphs, whether we inherit fill or stroke opacity from the outer
  2668   // text object.
  2669   // Use 3 bits to avoid signedness problems in MSVC.
  2670   nsStyleSVGOpacitySource mFillOpacitySource    : 3;
  2671   nsStyleSVGOpacitySource mStrokeOpacitySource  : 3;
  2673   // SVG glyph outer object inheritance for other properties
  2674   bool mStrokeDasharrayFromObject   : 1;
  2675   bool mStrokeDashoffsetFromObject  : 1;
  2676   bool mStrokeWidthFromObject       : 1;
  2678   bool HasMarker() const {
  2679     return mMarkerStart || mMarkerMid || mMarkerEnd;
  2682   /**
  2683    * Returns true if the stroke is not "none" and the stroke-opacity is greater
  2684    * than zero. This ignores stroke-widths as that depends on the context.
  2685    */
  2686   bool HasStroke() const {
  2687     return mStroke.mType != eStyleSVGPaintType_None && mStrokeOpacity > 0;
  2690   /**
  2691    * Returns true if the fill is not "none" and the fill-opacity is greater
  2692    * than zero.
  2693    */
  2694   bool HasFill() const {
  2695     return mFill.mType != eStyleSVGPaintType_None && mFillOpacity > 0;
  2697 };
  2699 struct nsStyleFilter {
  2700   nsStyleFilter();
  2701   nsStyleFilter(const nsStyleFilter& aSource);
  2702   ~nsStyleFilter();
  2704   nsStyleFilter& operator=(const nsStyleFilter& aOther);
  2706   bool operator==(const nsStyleFilter& aOther) const;
  2708   int32_t GetType() const {
  2709     return mType;
  2712   const nsStyleCoord& GetFilterParameter() const {
  2713     NS_ASSERTION(mType != NS_STYLE_FILTER_DROP_SHADOW &&
  2714                  mType != NS_STYLE_FILTER_URL &&
  2715                  mType != NS_STYLE_FILTER_NONE, "wrong filter type");
  2716     return mFilterParameter;
  2718   void SetFilterParameter(const nsStyleCoord& aFilterParameter,
  2719                           int32_t aType);
  2721   nsIURI* GetURL() const {
  2722     NS_ASSERTION(mType == NS_STYLE_FILTER_URL, "wrong filter type");
  2723     return mURL;
  2725   void SetURL(nsIURI* aURL);
  2727   nsCSSShadowArray* GetDropShadow() const {
  2728     NS_ASSERTION(mType == NS_STYLE_FILTER_DROP_SHADOW, "wrong filter type");
  2729     return mDropShadow;
  2731   void SetDropShadow(nsCSSShadowArray* aDropShadow);
  2733 private:
  2734   void ReleaseRef();
  2736   int32_t mType; // see NS_STYLE_FILTER_* constants in nsStyleConsts.h
  2737   nsStyleCoord mFilterParameter; // coord, percent, factor, angle
  2738   union {
  2739     nsIURI* mURL;
  2740     nsCSSShadowArray* mDropShadow;
  2741   };
  2742 };
  2744 template<>
  2745 struct nsTArray_CopyChooser<nsStyleFilter> {
  2746   typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
  2747 };
  2749 struct nsStyleSVGReset {
  2750   nsStyleSVGReset();
  2751   nsStyleSVGReset(const nsStyleSVGReset& aSource);
  2752   ~nsStyleSVGReset();
  2754   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2755     return aContext->AllocateFromShell(sz);
  2757   void Destroy(nsPresContext* aContext) {
  2758     this->~nsStyleSVGReset();
  2759     aContext->FreeToShell(sizeof(nsStyleSVGReset), this);
  2762   nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const;
  2763   static nsChangeHint MaxDifference() {
  2764     return NS_CombineHint(nsChangeHint_UpdateEffects,
  2765             NS_CombineHint(nsChangeHint_UpdateOverflow, NS_STYLE_HINT_REFLOW));
  2767   static nsChangeHint MaxDifferenceNeverInherited() {
  2768     // CalcDifference never returns nsChangeHint_NeedReflow or
  2769     // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
  2770     return NS_CombineHint(nsChangeHint_NeedReflow,
  2771                           nsChangeHint_ClearAncestorIntrinsics);
  2774   bool HasFilters() const {
  2775     return mFilters.Length() > 0;
  2778   nsCOMPtr<nsIURI> mClipPath;         // [reset]
  2779   nsTArray<nsStyleFilter> mFilters;   // [reset]
  2780   nsCOMPtr<nsIURI> mMask;             // [reset]
  2781   nscolor          mStopColor;        // [reset]
  2782   nscolor          mFloodColor;       // [reset]
  2783   nscolor          mLightingColor;    // [reset]
  2785   float            mStopOpacity;      // [reset]
  2786   float            mFloodOpacity;     // [reset]
  2788   uint8_t          mDominantBaseline; // [reset] see nsStyleConsts.h
  2789   uint8_t          mVectorEffect;     // [reset] see nsStyleConsts.h
  2790   uint8_t          mMaskType;         // [reset] see nsStyleConsts.h
  2791 };
  2793 struct nsStyleVariables {
  2794   nsStyleVariables();
  2795   nsStyleVariables(const nsStyleVariables& aSource);
  2796   ~nsStyleVariables();
  2798   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
  2799     return aContext->AllocateFromShell(sz);
  2801   void Destroy(nsPresContext* aContext) {
  2802     this->~nsStyleVariables();
  2803     aContext->FreeToShell(sizeof(nsStyleVariables), this);
  2806   nsChangeHint CalcDifference(const nsStyleVariables& aOther) const;
  2807   static nsChangeHint MaxDifference() {
  2808     return nsChangeHint(0);
  2810   static nsChangeHint MaxDifferenceNeverInherited() {
  2811     // CalcDifference never returns nsChangeHint_NeedReflow or
  2812     // nsChangeHint_ClearAncestorIntrinsics at all.
  2813     return nsChangeHint(0);
  2816   mozilla::CSSVariableValues mVariables;
  2817 };
  2819 #endif /* nsStyleStruct_h___ */

mercurial