summaryrefslogtreecommitdiffstats
path: root/layout/style/nsStyleStruct.h
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /layout/style/nsStyleStruct.h
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'layout/style/nsStyleStruct.h')
-rw-r--r--layout/style/nsStyleStruct.h4002
1 files changed, 4002 insertions, 0 deletions
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
new file mode 100644
index 000000000..ca5d03056
--- /dev/null
+++ b/layout/style/nsStyleStruct.h
@@ -0,0 +1,4002 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * structs that contain the data provided by nsStyleContext, the
+ * internal API for computed style data for an element
+ */
+
+#ifndef nsStyleStruct_h___
+#define nsStyleStruct_h___
+
+#include "mozilla/ArenaObjectID.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/CSSVariableValues.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/SheetType.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/StyleComplexColor.h"
+#include "mozilla/StyleStructContext.h"
+#include "mozilla/UniquePtr.h"
+#include "nsColor.h"
+#include "nsCoord.h"
+#include "nsMargin.h"
+#include "nsFont.h"
+#include "nsStyleCoord.h"
+#include "nsStyleConsts.h"
+#include "nsChangeHint.h"
+#include "nsPresContext.h"
+#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
+#include "nsTArray.h"
+#include "nsCSSValue.h"
+#include "imgRequestProxy.h"
+#include "Orientation.h"
+#include "CounterStyleManager.h"
+#include <cstddef> // offsetof()
+#include <utility>
+#include "X11UndefineNone.h"
+
+class nsIFrame;
+class nsIURI;
+class nsStyleContext;
+class nsTextFrame;
+class imgIContainer;
+struct nsStyleVisibility;
+namespace mozilla {
+namespace dom {
+class ImageTracker;
+} // namespace dom
+} // namespace mozilla
+
+// Includes nsStyleStructID.
+#include "nsStyleStructFwd.h"
+
+// Bits for each struct.
+// NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
+#define NS_STYLE_INHERIT_MASK 0x000ffffff
+
+// Bits for inherited structs.
+#define NS_STYLE_INHERITED_STRUCT_MASK \
+ ((nsStyleStructID_size_t(1) << nsStyleStructID_Inherited_Count) - 1)
+// Bits for reset structs.
+#define NS_STYLE_RESET_STRUCT_MASK \
+ (((nsStyleStructID_size_t(1) << nsStyleStructID_Reset_Count) - 1) \
+ << nsStyleStructID_Inherited_Count)
+
+// Additional bits for nsStyleContext's mBits:
+// See nsStyleContext::HasTextDecorationLines
+#define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000
+// See nsStyleContext::HasPseudoElementData.
+#define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA 0x002000000
+// See nsStyleContext::RelevantLinkIsVisited
+#define NS_STYLE_RELEVANT_LINK_VISITED 0x004000000
+// See nsStyleContext::IsStyleIfVisited
+#define NS_STYLE_IS_STYLE_IF_VISITED 0x008000000
+// See nsStyleContext::HasChildThatUsesGrandancestorStyle
+#define NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE 0x010000000
+// See nsStyleContext::IsShared
+#define NS_STYLE_IS_SHARED 0x020000000
+// See nsStyleContext::AssertStructsNotUsedElsewhere
+// (This bit is currently only used in #ifdef DEBUG code.)
+#define NS_STYLE_IS_GOING_AWAY 0x040000000
+// See nsStyleContext::ShouldSuppressLineBreak
+#define NS_STYLE_SUPPRESS_LINEBREAK 0x080000000
+// See nsStyleContext::IsInDisplayNoneSubtree
+#define NS_STYLE_IN_DISPLAY_NONE_SUBTREE 0x100000000
+// See nsStyleContext::FindChildWithRules
+#define NS_STYLE_INELIGIBLE_FOR_SHARING 0x200000000
+// See nsStyleContext::HasChildThatUsesResetStyle
+#define NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE 0x400000000
+// See nsStyleContext::IsTextCombined
+#define NS_STYLE_IS_TEXT_COMBINED 0x800000000
+// See nsStyleContext::GetPseudoEnum
+#define NS_STYLE_CONTEXT_TYPE_SHIFT 36
+
+// Additional bits for nsRuleNode's mDependentBits:
+#define NS_RULE_NODE_IS_ANIMATION_RULE 0x01000000
+// Free bit 0x02000000
+#define NS_RULE_NODE_USED_DIRECTLY 0x04000000
+#define NS_RULE_NODE_IS_IMPORTANT 0x08000000
+#define NS_RULE_NODE_LEVEL_MASK 0xf0000000
+#define NS_RULE_NODE_LEVEL_SHIFT 28
+
+// Additional bits for nsRuleNode's mNoneBits:
+#define NS_RULE_NODE_HAS_ANIMATION_DATA 0x80000000
+
+static_assert(int(mozilla::SheetType::Count) - 1 <=
+ (NS_RULE_NODE_LEVEL_MASK >> NS_RULE_NODE_LEVEL_SHIFT),
+ "NS_RULE_NODE_LEVEL_MASK cannot fit SheetType");
+
+static_assert(NS_STYLE_INHERIT_MASK == (1 << nsStyleStructID_Length) - 1,
+ "NS_STYLE_INHERIT_MASK is not correct");
+
+static_assert((NS_RULE_NODE_IS_ANIMATION_RULE & NS_STYLE_INHERIT_MASK) == 0,
+ "NS_RULE_NODE_IS_ANIMATION_RULE must not overlap the style struct bits.");
+
+namespace mozilla {
+
+struct Position {
+ using Coord = nsStyleCoord::CalcValue;
+
+ Coord mXPosition, mYPosition;
+
+ // Initialize nothing
+ Position() {}
+
+ // Sets both mXPosition and mYPosition to the given percent value for the
+ // initial property-value (e.g. 0.0f for "0% 0%", or 0.5f for "50% 50%")
+ void SetInitialPercentValues(float aPercentVal);
+
+ // Sets both mXPosition and mYPosition to 0 (app units) for the
+ // initial property-value as a length with no percentage component.
+ void SetInitialZeroValues();
+
+ // True if the effective background image position described by this depends
+ // on the size of the corresponding frame.
+ bool DependsOnPositioningAreaSize() const {
+ return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
+ }
+
+ bool operator==(const Position& aOther) const {
+ return mXPosition == aOther.mXPosition &&
+ mYPosition == aOther.mYPosition;
+ }
+ bool operator!=(const Position& aOther) const {
+ return !(*this == aOther);
+ }
+};
+
+} // namespace mozilla
+
+// The lifetime of these objects is managed by the presshell's arena.
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont
+{
+ nsStyleFont(const nsFont& aFont, StyleStructContext aContext);
+ nsStyleFont(const nsStyleFont& aStyleFont);
+ explicit nsStyleFont(StyleStructContext aContext);
+ ~nsStyleFont() {
+ MOZ_COUNT_DTOR(nsStyleFont);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return NS_STYLE_HINT_REFLOW |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ /**
+ * Return aSize multiplied by the current text zoom factor (in aPresContext).
+ * aSize is allowed to be negative, but the caller is expected to deal with
+ * negative results. The result is clamped to nscoord_MIN .. nscoord_MAX.
+ */
+ static nscoord ZoomText(StyleStructContext aContext, nscoord aSize);
+ /**
+ * Return aSize divided by the current text zoom factor (in aPresContext).
+ * aSize is allowed to be negative, but the caller is expected to deal with
+ * negative results. The result is clamped to nscoord_MIN .. nscoord_MAX.
+ */
+ static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
+ static already_AddRefed<nsIAtom> GetLanguage(StyleStructContext aPresContext);
+
+ void* operator new(size_t sz, nsStyleFont* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleFont, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ void EnableZoom(nsPresContext* aContext, bool aEnable);
+
+ nsFont mFont; // [inherited]
+ nscoord mSize; // [inherited] Our "computed size". Can be different
+ // from mFont.size which is our "actual size" and is
+ // enforced to be >= the user's preferred min-size.
+ // mFont.size should be used for display purposes
+ // while mSize is the value to return in
+ // getComputedStyle() for example.
+ uint8_t mGenericID; // [inherited] generic CSS font family, if any;
+ // value is a kGenericFont_* constant, see nsFont.h.
+
+ // MathML scriptlevel support
+ int8_t mScriptLevel; // [inherited]
+ // MathML mathvariant support
+ uint8_t mMathVariant; // [inherited]
+ // MathML displaystyle support
+ uint8_t mMathDisplay; // [inherited]
+
+ // allow different min font-size for certain cases
+ uint8_t mMinFontSizeRatio; // [inherited] percent * 100
+
+ // was mLanguage set based on a lang attribute in the document?
+ bool mExplicitLanguage; // [inherited]
+
+ // should calls to ZoomText() and UnZoomText() be made to the font
+ // size on this nsStyleFont?
+ bool mAllowZoom; // [inherited]
+
+ // The value mSize would have had if scriptminsize had never been applied
+ nscoord mScriptUnconstrainedSize;
+ nscoord mScriptMinSize; // [inherited] length
+ float mScriptSizeMultiplier; // [inherited]
+ nsCOMPtr<nsIAtom> mLanguage; // [inherited]
+};
+
+struct nsStyleGradientStop
+{
+ nsStyleCoord mLocation; // percent, coord, calc, none
+ nscolor mColor;
+ bool mIsInterpolationHint;
+
+ // Use ==/!= on nsStyleGradient instead of on the gradient stop.
+ bool operator==(const nsStyleGradientStop&) const = delete;
+ bool operator!=(const nsStyleGradientStop&) const = delete;
+};
+
+class nsStyleGradient final
+{
+public:
+ nsStyleGradient();
+ uint8_t mShape; // NS_STYLE_GRADIENT_SHAPE_*
+ uint8_t mSize; // NS_STYLE_GRADIENT_SIZE_*;
+ // not used (must be FARTHEST_CORNER) for linear shape
+ bool mRepeating;
+ bool mLegacySyntax;
+
+ nsStyleCoord mBgPosX; // percent, coord, calc, none
+ nsStyleCoord mBgPosY; // percent, coord, calc, none
+ nsStyleCoord mAngle; // none, angle
+
+ nsStyleCoord mRadiusX; // percent, coord, calc, none
+ nsStyleCoord mRadiusY; // percent, coord, calc, none
+
+ // stops are in the order specified in the stylesheet
+ nsTArray<nsStyleGradientStop> mStops;
+
+ bool operator==(const nsStyleGradient& aOther) const;
+ bool operator!=(const nsStyleGradient& aOther) const {
+ return !(*this == aOther);
+ }
+
+ bool IsOpaque();
+ bool HasCalc();
+ uint32_t Hash(PLDHashNumber aHash);
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleGradient)
+
+private:
+ // Private destructor, to discourage deletion outside of Release():
+ ~nsStyleGradient() {}
+
+ nsStyleGradient(const nsStyleGradient& aOther) = delete;
+ nsStyleGradient& operator=(const nsStyleGradient& aOther) = delete;
+};
+
+/**
+ * A wrapper for an imgRequestProxy that supports off-main-thread creation
+ * and equality comparison.
+ *
+ * An nsStyleImageRequest can be created in two ways:
+ *
+ * 1. Using the constructor that takes an imgRequestProxy. This must
+ * be called from the main thread. The nsStyleImageRequest is
+ * immediately considered "resolved", and the get() method that
+ * returns the imgRequestProxy can be called.
+ *
+ * 2. Using the constructor that takes the URL, base URI, referrer
+ * and principal that can be used to inititiate an image load and
+ * produce an imgRequestProxy later. This can be called from
+ * any thread. The nsStyleImageRequest is not considered "resolved"
+ * at this point, and the Resolve() method must be called later
+ * to initiate the image load and make calls to get() valid.
+ *
+ * Calls to TrackImage(), UntrackImage(), LockImage(), UnlockImage() and
+ * RequestDiscard() are made to the imgRequestProxy and ImageTracker as
+ * appropriate, according to the mode flags passed in to the constructor.
+ *
+ * The main thread constructor takes a pointer to the css::ImageValue that
+ * is the specified url() value, while the off-main-thread constructor
+ * creates a new css::ImageValue to represent the url() information passed
+ * to the constructor. This ImageValue is held on to for the comparisons done
+ * in DefinitelyEquals(), so that we don't need to call into the non-OMT-safe
+ * Equals() on the nsIURI objects returned from imgRequestProxy::GetURI().
+ */
+class nsStyleImageRequest
+{
+public:
+ // Flags describing whether the imgRequestProxy must be tracked in the
+ // ImageTracker, whether LockImage/UnlockImage calls will be made
+ // when obtaining and releasing the imgRequestProxy, and whether
+ // RequestDiscard will be called on release.
+ enum class Mode : uint8_t {
+ // The imgRequestProxy will be added to the ImageTracker when resolved
+ // Without this flag, the nsStyleImageRequest itself will call LockImage/
+ // UnlockImage on the imgRequestProxy, rather than leaving locking to the
+ // ImageTracker to manage.
+ //
+ // This flag is currently used by all nsStyleImageRequests except
+ // those for list-style-image and cursor.
+ Track = 0x1,
+
+ // The imgRequestProxy will have its RequestDiscard method called when
+ // the nsStyleImageRequest is going away.
+ //
+ // This is currently used only for cursor images.
+ Discard = 0x2,
+ };
+
+ // Must be called from the main thread.
+ //
+ // aImageTracker must be non-null iff aModeFlags contains Track.
+ nsStyleImageRequest(Mode aModeFlags,
+ imgRequestProxy* aRequestProxy,
+ mozilla::css::ImageValue* aImageValue,
+ mozilla::dom::ImageTracker* aImageTracker);
+
+ // Can be called from any thread, but Resolve() must be called later
+ // on the main thread before get() can be used.
+ nsStyleImageRequest(
+ Mode aModeFlags,
+ nsStringBuffer* aURLBuffer,
+ already_AddRefed<mozilla::PtrHolder<nsIURI>> aBaseURI,
+ already_AddRefed<mozilla::PtrHolder<nsIURI>> aReferrer,
+ already_AddRefed<mozilla::PtrHolder<nsIPrincipal>> aPrincipal);
+
+ bool Resolve(nsPresContext* aPresContext);
+ bool IsResolved() const { return mResolved; }
+
+ imgRequestProxy* get() {
+ MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
+ MOZ_ASSERT(NS_IsMainThread());
+ return mRequestProxy.get();
+ }
+ const imgRequestProxy* get() const {
+ return const_cast<nsStyleImageRequest*>(this)->get();
+ }
+
+ // Returns whether the ImageValue objects in the two nsStyleImageRequests
+ // return true from URLValueData::DefinitelyEqualURIs.
+ bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleImageRequest);
+
+private:
+ ~nsStyleImageRequest();
+ nsStyleImageRequest& operator=(const nsStyleImageRequest& aOther) = delete;
+
+ void MaybeTrackAndLock();
+
+ RefPtr<imgRequestProxy> mRequestProxy;
+ RefPtr<mozilla::css::ImageValue> mImageValue;
+ RefPtr<mozilla::dom::ImageTracker> mImageTracker;
+
+ Mode mModeFlags;
+ bool mResolved;
+};
+
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsStyleImageRequest::Mode)
+
+enum nsStyleImageType {
+ eStyleImageType_Null,
+ eStyleImageType_Image,
+ eStyleImageType_Gradient,
+ eStyleImageType_Element
+};
+
+struct CachedBorderImageData
+{
+ // Caller are expected to ensure that the value of aSVGViewportSize is
+ // different from the cached one since the method won't do the check.
+ void SetCachedSVGViewportSize(const mozilla::Maybe<nsSize>& aSVGViewportSize);
+ const mozilla::Maybe<nsSize>& GetCachedSVGViewportSize();
+ void PurgeCachedImages();
+ void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage);
+ imgIContainer* GetSubImage(uint8_t aIndex);
+
+private:
+ // If this is a SVG border-image, we save the size of the SVG viewport that
+ // we used when rasterizing any cached border-image subimages. (The viewport
+ // size matters for percent-valued sizes & positions in inner SVG doc).
+ mozilla::Maybe<nsSize> mCachedSVGViewportSize;
+ nsCOMArray<imgIContainer> mSubImages;
+};
+
+/**
+ * Represents a paintable image of one of the following types.
+ * (1) A real image loaded from an external source.
+ * (2) A CSS linear or radial gradient.
+ * (3) An element within a document, or an <img>, <video>, or <canvas> element
+ * not in a document.
+ * (*) Optionally a crop rect can be set to paint a partial (rectangular)
+ * region of an image. (Currently, this feature is only supported with an
+ * image of type (1)).
+ */
+struct nsStyleImage
+{
+ nsStyleImage();
+ ~nsStyleImage();
+ nsStyleImage(const nsStyleImage& aOther);
+ nsStyleImage& operator=(const nsStyleImage& aOther);
+
+ void SetNull();
+ void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
+ void SetGradientData(nsStyleGradient* aGradient);
+ void SetElementId(const char16_t* aElementId);
+ void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
+
+ void ResolveImage(nsPresContext* aContext) {
+ MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
+ if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
+ mImage->Resolve(aContext);
+ }
+ }
+
+ nsStyleImageType GetType() const {
+ return mType;
+ }
+ nsStyleImageRequest* GetImageRequest() const {
+ MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
+ MOZ_ASSERT(mImage);
+ return mImage;
+ }
+ imgRequestProxy* GetImageData() const {
+ return GetImageRequest()->get();
+ }
+ nsStyleGradient* GetGradientData() const {
+ NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
+ return mGradient;
+ }
+ const char16_t* GetElementId() const {
+ NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
+ return mElementId;
+ }
+ const mozilla::UniquePtr<nsStyleSides>& GetCropRect() const {
+ NS_ASSERTION(mType == eStyleImageType_Image,
+ "Only image data can have a crop rect");
+ return mCropRect;
+ }
+
+ /**
+ * Compute the actual crop rect in pixels, using the source image bounds.
+ * The computation involves converting percentage unit to pixel unit and
+ * clamping each side value to fit in the source image bounds.
+ * @param aActualCropRect the computed actual crop rect.
+ * @param aIsEntireImage true iff |aActualCropRect| is identical to the
+ * source image bounds.
+ * @return true iff |aActualCropRect| holds a meaningful value.
+ */
+ bool ComputeActualCropRect(nsIntRect& aActualCropRect,
+ bool* aIsEntireImage = nullptr) const;
+
+ /**
+ * Starts the decoding of a image.
+ */
+ nsresult StartDecoding() const;
+ /**
+ * @return true if the item is definitely opaque --- i.e., paints every
+ * pixel within its bounds opaquely, and the bounds contains at least a pixel.
+ */
+ bool IsOpaque() const;
+ /**
+ * @return true if this image is fully loaded, and its size is calculated;
+ * always returns true if |mType| is |eStyleImageType_Gradient| or
+ * |eStyleImageType_Element|.
+ */
+ bool IsComplete() const;
+ /**
+ * @return true if this image is loaded without error;
+ * always returns true if |mType| is |eStyleImageType_Gradient| or
+ * |eStyleImageType_Element|.
+ */
+ bool IsLoaded() const;
+ /**
+ * @return true if it is 100% confident that this image contains no pixel
+ * to draw.
+ */
+ bool IsEmpty() const {
+ // There are some other cases when the image will be empty, for example
+ // when the crop rect is empty. However, checking the emptiness of crop
+ // rect is non-trivial since each side value can be specified with
+ // percentage unit, which can not be evaluated until the source image size
+ // is available. Therefore, we currently postpone the evaluation of crop
+ // rect until the actual rendering time --- alternatively until GetOpaqueRegion()
+ // is called.
+ return mType == eStyleImageType_Null;
+ }
+
+ bool operator==(const nsStyleImage& aOther) const;
+ bool operator!=(const nsStyleImage& aOther) const {
+ return !(*this == aOther);
+ }
+
+ bool ImageDataEquals(const nsStyleImage& aOther) const
+ {
+ return GetType() == eStyleImageType_Image &&
+ aOther.GetType() == eStyleImageType_Image &&
+ GetImageData() == aOther.GetImageData();
+ }
+
+ // These methods are used for the caller to caches the sub images created
+ // during a border-image paint operation
+ inline void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const;
+ inline imgIContainer* GetSubImage(uint8_t aIndex) const;
+ void PurgeCacheForViewportChange(
+ const mozilla::Maybe<nsSize>& aSVGViewportSize,
+ const bool aHasIntrinsicRatio) const;
+
+private:
+ void DoCopy(const nsStyleImage& aOther);
+ void EnsureCachedBIData() const;
+
+ // This variable keeps some cache data for border image and is lazily
+ // allocated since it is only used in border image case.
+ mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
+
+ nsStyleImageType mType;
+ union {
+ nsStyleImageRequest* mImage;
+ nsStyleGradient* mGradient;
+ char16_t* mElementId;
+ };
+
+ // This is _currently_ used only in conjunction with eStyleImageType_Image.
+ mozilla::UniquePtr<nsStyleSides> mCropRect;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
+{
+ explicit nsStyleColor(StyleStructContext aContext);
+ nsStyleColor(const nsStyleColor& aOther);
+ ~nsStyleColor() {
+ MOZ_COUNT_DTOR(nsStyleColor);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ nscolor CalcComplexColor(const mozilla::StyleComplexColor& aColor) const {
+ return mozilla::LinearBlendColors(aColor.mColor, mColor,
+ aColor.mForegroundRatio);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_RepaintFrame;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants at all.
+ return nsChangeHint(0);
+ }
+
+ void* operator new(size_t sz, nsStyleColor* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColor, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleColor();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleColor, this);
+ }
+
+ // Don't add ANY members to this struct! We can achieve caching in the rule
+ // tree (rather than the style tree) by letting color stay by itself! -dwh
+ nscolor mColor; // [inherited]
+};
+
+/**
+ * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
+ * always has length >= 1.
+ */
+template<typename T>
+class nsStyleAutoArray
+{
+public:
+ // This constructor places a single element in mFirstElement.
+ enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT };
+ explicit nsStyleAutoArray(WithSingleInitialElement) {}
+ nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; }
+ nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) {
+ mFirstElement = aOther.mFirstElement;
+ mOtherElements = aOther.mOtherElements;
+ return *this;
+ }
+
+ bool operator==(const nsStyleAutoArray& aOther) const {
+ return Length() == aOther.Length() &&
+ mFirstElement == aOther.mFirstElement &&
+ mOtherElements == aOther.mOtherElements;
+ }
+ bool operator!=(const nsStyleAutoArray& aOther) const {
+ return !(*this == aOther);
+ }
+
+ size_t Length() const {
+ return mOtherElements.Length() + 1;
+ }
+ const T& operator[](size_t aIndex) const {
+ return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
+ }
+ T& operator[](size_t aIndex) {
+ return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
+ }
+
+ void EnsureLengthAtLeast(size_t aMinLen) {
+ if (aMinLen > 0) {
+ mOtherElements.EnsureLengthAtLeast(aMinLen - 1);
+ }
+ }
+
+ void SetLengthNonZero(size_t aNewLen) {
+ MOZ_ASSERT(aNewLen > 0);
+ mOtherElements.SetLength(aNewLen - 1);
+ }
+
+ void TruncateLengthNonZero(size_t aNewLen) {
+ MOZ_ASSERT(aNewLen > 0);
+ MOZ_ASSERT(aNewLen <= Length());
+ mOtherElements.TruncateLength(aNewLen - 1);
+ }
+
+private:
+ T mFirstElement;
+ nsTArray<T> mOtherElements;
+};
+
+struct nsStyleImageLayers {
+ // Indices into kBackgroundLayerTable and kMaskLayerTable
+ enum {
+ shorthand = 0,
+ color,
+ image,
+ repeat,
+ positionX,
+ positionY,
+ clip,
+ origin,
+ size,
+ attachment,
+ maskMode,
+ composite
+ };
+
+ enum class LayerType : uint8_t {
+ Background = 0,
+ Mask
+ };
+
+ explicit nsStyleImageLayers(LayerType aType);
+ nsStyleImageLayers(const nsStyleImageLayers &aSource);
+ ~nsStyleImageLayers() {
+ MOZ_COUNT_DTOR(nsStyleImageLayers);
+ }
+
+ static bool IsInitialPositionForLayerType(mozilla::Position aPosition, LayerType aType);
+
+ struct Size;
+ friend struct Size;
+ struct Size {
+ struct Dimension : public nsStyleCoord::CalcValue {
+ nscoord ResolveLengthPercentage(nscoord aAvailable) const {
+ double d = double(mPercent) * double(aAvailable) + double(mLength);
+ if (d < 0.0) {
+ return 0;
+ }
+ return NSToCoordRoundWithClamp(float(d));
+ }
+ };
+ Dimension mWidth, mHeight;
+
+ bool IsInitialValue() const {
+ return mWidthType == eAuto && mHeightType == eAuto;
+ }
+
+ nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
+ MOZ_ASSERT(mWidthType == eLengthPercentage,
+ "resolving non-length/percent dimension!");
+ return mWidth.ResolveLengthPercentage(aBgPositioningArea.width);
+ }
+
+ nscoord ResolveHeightLengthPercentage(const nsSize& aBgPositioningArea) const {
+ MOZ_ASSERT(mHeightType == eLengthPercentage,
+ "resolving non-length/percent dimension!");
+ return mHeight.ResolveLengthPercentage(aBgPositioningArea.height);
+ }
+
+ // Except for eLengthPercentage, Dimension types which might change
+ // how a layer is painted when the corresponding frame's dimensions
+ // change *must* precede all dimension types which are agnostic to
+ // frame size; see DependsOnDependsOnPositioningAreaSizeSize.
+ enum DimensionType {
+ // If one of mWidth and mHeight is eContain or eCover, then both are.
+ // NOTE: eContain and eCover *must* be equal to NS_STYLE_BG_SIZE_CONTAIN
+ // and NS_STYLE_BG_SIZE_COVER (in kBackgroundSizeKTable).
+ eContain, eCover,
+
+ eAuto,
+ eLengthPercentage,
+ eDimensionType_COUNT
+ };
+ uint8_t mWidthType, mHeightType;
+
+ // True if the effective image size described by this depends on the size of
+ // the corresponding frame, when aImage (which must not have null type) is
+ // the background image.
+ bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
+
+ // Initialize nothing
+ Size() {}
+
+ // Initialize to initial values
+ void SetInitialValues();
+
+ bool operator==(const Size& aOther) const;
+ bool operator!=(const Size& aOther) const {
+ return !(*this == aOther);
+ }
+ };
+
+ struct Repeat;
+ friend struct Repeat;
+ struct Repeat {
+ uint8_t mXRepeat, mYRepeat;
+
+ // Initialize nothing
+ Repeat() {}
+
+ bool IsInitialValue() const {
+ return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT &&
+ mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
+ }
+
+ bool DependsOnPositioningAreaSize() const {
+ return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_SPACE ||
+ mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_SPACE;
+ }
+
+ // Initialize to initial values
+ void SetInitialValues() {
+ mXRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
+ mYRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
+ }
+
+ bool operator==(const Repeat& aOther) const {
+ return mXRepeat == aOther.mXRepeat &&
+ mYRepeat == aOther.mYRepeat;
+ }
+ bool operator!=(const Repeat& aOther) const {
+ return !(*this == aOther);
+ }
+ };
+
+ struct Layer;
+ friend struct Layer;
+ struct Layer {
+ nsStyleImage mImage; // [reset]
+ RefPtr<mozilla::css::URLValueData> mSourceURI; // [reset]
+ // mask-only property
+ // This property is used for mask layer only.
+ // For a background layer, it should always
+ // be the initial value, which is nullptr.
+ // Store mask-image URI so that we can resolve
+ // SVG mask path later. (Might be a URLValue
+ // or an ImageValue.)
+ mozilla::Position mPosition; // [reset]
+ Size mSize; // [reset]
+ uint8_t mClip; // [reset] See nsStyleConsts.h
+ MOZ_INIT_OUTSIDE_CTOR
+ uint8_t mOrigin; // [reset] See nsStyleConsts.h
+ uint8_t mAttachment; // [reset] See nsStyleConsts.h
+ // background-only property
+ // This property is used for background layer
+ // only. For a mask layer, it should always
+ // be the initial value, which is
+ // NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL.
+ uint8_t mBlendMode; // [reset] See nsStyleConsts.h
+ // background-only property
+ // This property is used for background layer
+ // only. For a mask layer, it should always
+ // be the initial value, which is
+ // NS_STYLE_BLEND_NORMAL.
+ uint8_t mComposite; // [reset] See nsStyleConsts.h
+ // mask-only property
+ // This property is used for mask layer only.
+ // For a background layer, it should always
+ // be the initial value, which is
+ // NS_STYLE_COMPOSITE_MODE_ADD.
+ uint8_t mMaskMode; // [reset] See nsStyleConsts.h
+ // mask-only property
+ // This property is used for mask layer only.
+ // For a background layer, it should always
+ // be the initial value, which is
+ // NS_STYLE_MASK_MODE_MATCH_SOURCE.
+ Repeat mRepeat; // [reset] See nsStyleConsts.h
+
+ // This constructor does not initialize mRepeat or mOrigin and Initialize()
+ // must be called to do that.
+ Layer();
+ ~Layer();
+
+ // Initialize mRepeat and mOrigin by specified layer type
+ void Initialize(LayerType aType);
+
+ void ResolveImage(nsPresContext* aContext) {
+ if (mImage.GetType() == eStyleImageType_Image) {
+ mImage.ResolveImage(aContext);
+ }
+ }
+
+ // True if the rendering of this layer might change when the size
+ // of the background positioning area changes. This is true for any
+ // non-solid-color background whose position or size depends on
+ // the size of the positioning area. It's also true for SVG images
+ // whose root <svg> node has a viewBox.
+ bool RenderingMightDependOnPositioningAreaSizeChange() const;
+
+ // Compute the change hint required by changes in just this layer.
+ nsChangeHint CalcDifference(const Layer& aNewLayer) const;
+
+ // An equality operator that compares the images using URL-equality
+ // rather than pointer-equality.
+ bool operator==(const Layer& aOther) const;
+ bool operator!=(const Layer& aOther) const {
+ return !(*this == aOther);
+ }
+ };
+
+ // The (positive) number of computed values of each property, since
+ // the lengths of the lists are independent.
+ uint32_t mAttachmentCount,
+ mClipCount,
+ mOriginCount,
+ mRepeatCount,
+ mPositionXCount,
+ mPositionYCount,
+ mImageCount,
+ mSizeCount,
+ mMaskModeCount,
+ mBlendModeCount,
+ mCompositeCount;
+
+ // Layers are stored in an array, matching the top-to-bottom order in
+ // which they are specified in CSS. The number of layers to be used
+ // should come from the background-image property. We create
+ // additional |Layer| objects for *any* property, not just
+ // background-image. This means that the bottommost layer that
+ // callers in layout care about (which is also the one whose
+ // background-clip applies to the background-color) may not be last
+ // layer. In layers below the bottom layer, properties will be
+ // uninitialized unless their count, above, indicates that they are
+ // present.
+ nsStyleAutoArray<Layer> mLayers;
+
+ const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
+
+ void ResolveImages(nsPresContext* aContext) {
+ for (uint32_t i = 0; i < mImageCount; ++i) {
+ mLayers[i].ResolveImage(aContext);
+ }
+ }
+
+ nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
+ nsStyleImageLayers::LayerType aType) const;
+
+ bool HasLayerWithImage() const;
+ nsStyleImageLayers& operator=(const nsStyleImageLayers& aOther);
+
+ static const nsCSSPropertyID kBackgroundLayerTable[];
+ static const nsCSSPropertyID kMaskLayerTable[];
+
+ #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
+ for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
+ #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
+ NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < (layers_).mImageCount, "Invalid layer start!"); \
+ NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
+ for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
+ explicit nsStyleBackground(StyleStructContext aContext);
+ nsStyleBackground(const nsStyleBackground& aOther);
+ ~nsStyleBackground();
+
+ // Resolves and tracks the images in mImage. Only called with a Servo-backed
+ // style system, where those images must be resolved later than the OMT
+ // nsStyleBackground constructor call.
+ void FinishStyle(nsPresContext* aPresContext);
+
+ void* operator new(size_t sz, nsStyleBackground* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ nsChangeHint CalcDifference(const nsStyleBackground& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_UpdateEffects |
+ nsChangeHint_RepaintFrame |
+ nsChangeHint_UpdateBackgroundPosition |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants at all.
+ return nsChangeHint(0);
+ }
+
+ // True if this background is completely transparent.
+ bool IsTransparent() const;
+
+ // We have to take slower codepaths for fixed background attachment,
+ // but we don't want to do that when there's no image.
+ // Not inline because it uses an nsCOMPtr<imgIRequest>
+ // FIXME: Should be in nsStyleStructInlines.h.
+ bool HasFixedBackground(nsIFrame* aFrame) const;
+
+ // Checks to see if this has a non-empty image with "local" attachment.
+ // This is defined in nsStyleStructInlines.h.
+ inline bool HasLocalBackground() const;
+
+ const nsStyleImageLayers::Layer& BottomLayer() const { return mImage.BottomLayer(); }
+
+ nsStyleImageLayers mImage;
+ nscolor mBackgroundColor; // [reset]
+};
+
+#define NS_SPACING_MARGIN 0
+#define NS_SPACING_PADDING 1
+#define NS_SPACING_BORDER 2
+
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin
+{
+ explicit nsStyleMargin(StyleStructContext aContext);
+ nsStyleMargin(const nsStyleMargin& aMargin);
+ ~nsStyleMargin() {
+ MOZ_COUNT_DTOR(nsStyleMargin);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleMargin* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ nsChangeHint CalcDifference(const nsStyleMargin& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference can return all of the reflow hints sometimes not
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint(0);
+ }
+
+ bool GetMargin(nsMargin& aMargin) const
+ {
+ if (!mMargin.ConvertsToLength()) {
+ return false;
+ }
+
+ NS_FOR_CSS_SIDES(side) {
+ aMargin.Side(side) = mMargin.ToLength(side);
+ }
+ return true;
+ }
+
+ // Return true if either the start or end side in the axis is 'auto'.
+ // (defined in WritingModes.h since we need the full WritingMode type)
+ inline bool HasBlockAxisAuto(mozilla::WritingMode aWM) const;
+ inline bool HasInlineAxisAuto(mozilla::WritingMode aWM) const;
+
+ nsStyleSides mMargin; // [reset] coord, percent, calc, auto
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding
+{
+ explicit nsStylePadding(StyleStructContext aContext);
+ nsStylePadding(const nsStylePadding& aPadding);
+ ~nsStylePadding() {
+ MOZ_COUNT_DTOR(nsStylePadding);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStylePadding* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ nsChangeHint CalcDifference(const nsStylePadding& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as
+ // a hint not handled for descendants. We could (and perhaps
+ // should) return nsChangeHint_NeedReflow and
+ // nsChangeHint_ReflowChangesSizeOrPosition as always handled for
+ // descendants, but since they're always returned in conjunction
+ // with nsChangeHint_ClearAncestorIntrinsics (which is not), it
+ // won't ever lead to any optimization in
+ // nsStyleContext::CalcStyleDifference.
+ return nsChangeHint(0);
+ }
+
+ nsStyleSides mPadding; // [reset] coord, percent, calc
+
+ bool IsWidthDependent() const {
+ return !mPadding.ConvertsToLength();
+ }
+
+ bool GetPadding(nsMargin& aPadding) const
+ {
+ if (!mPadding.ConvertsToLength()) {
+ return false;
+ }
+
+ NS_FOR_CSS_SIDES(side) {
+ // Clamp negative calc() to 0.
+ aPadding.Side(side) = std::max(mPadding.ToLength(side), 0);
+ }
+ return true;
+ }
+};
+
+struct nsBorderColors
+{
+ nsBorderColors* mNext;
+ nscolor mColor;
+
+ nsBorderColors() : mNext(nullptr), mColor(NS_RGB(0,0,0)) {}
+ explicit nsBorderColors(const nscolor& aColor) : mNext(nullptr), mColor(aColor) {}
+ ~nsBorderColors();
+
+ nsBorderColors* Clone() const { return Clone(true); }
+
+ static bool Equal(const nsBorderColors* c1,
+ const nsBorderColors* c2) {
+ if (c1 == c2) {
+ return true;
+ }
+ while (c1 && c2) {
+ if (c1->mColor != c2->mColor) {
+ return false;
+ }
+ c1 = c1->mNext;
+ c2 = c2->mNext;
+ }
+ // both should be nullptr if these are equal, otherwise one
+ // has more colors than another
+ return !c1 && !c2;
+ }
+
+private:
+ nsBorderColors* Clone(bool aDeep) const;
+};
+
+struct nsCSSShadowItem
+{
+ nscoord mXOffset;
+ nscoord mYOffset;
+ nscoord mRadius;
+ nscoord mSpread;
+
+ nscolor mColor;
+ bool mHasColor; // Whether mColor should be used
+ bool mInset;
+
+ nsCSSShadowItem() : mHasColor(false) {
+ MOZ_COUNT_CTOR(nsCSSShadowItem);
+ }
+ ~nsCSSShadowItem() {
+ MOZ_COUNT_DTOR(nsCSSShadowItem);
+ }
+
+ bool operator==(const nsCSSShadowItem& aOther) const {
+ return (mXOffset == aOther.mXOffset &&
+ mYOffset == aOther.mYOffset &&
+ mRadius == aOther.mRadius &&
+ mHasColor == aOther.mHasColor &&
+ mSpread == aOther.mSpread &&
+ mInset == aOther.mInset &&
+ (!mHasColor || mColor == aOther.mColor));
+ }
+ bool operator!=(const nsCSSShadowItem& aOther) const {
+ return !(*this == aOther);
+ }
+};
+
+class nsCSSShadowArray final
+{
+public:
+ void* operator new(size_t aBaseSize, uint32_t aArrayLen) {
+ // We can allocate both this nsCSSShadowArray and the
+ // actual array in one allocation. The amount of memory to
+ // allocate is equal to the class's size + the number of bytes for all
+ // but the first array item (because aBaseSize includes one
+ // item, see the private declarations)
+ return ::operator new(aBaseSize +
+ (aArrayLen - 1) * sizeof(nsCSSShadowItem));
+ }
+
+ explicit nsCSSShadowArray(uint32_t aArrayLen) :
+ mLength(aArrayLen)
+ {
+ MOZ_COUNT_CTOR(nsCSSShadowArray);
+ for (uint32_t i = 1; i < mLength; ++i) {
+ // Make sure we call the constructors of each nsCSSShadowItem
+ // (the first one is called for us because we declared it under private)
+ new (&mArray[i]) nsCSSShadowItem();
+ }
+ }
+
+private:
+ // Private destructor, to discourage deletion outside of Release():
+ ~nsCSSShadowArray() {
+ MOZ_COUNT_DTOR(nsCSSShadowArray);
+ for (uint32_t i = 1; i < mLength; ++i) {
+ mArray[i].~nsCSSShadowItem();
+ }
+ }
+
+public:
+ uint32_t Length() const { return mLength; }
+ nsCSSShadowItem* ShadowAt(uint32_t i) {
+ MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!");
+ return &mArray[i];
+ }
+ const nsCSSShadowItem* ShadowAt(uint32_t i) const {
+ MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!");
+ return &mArray[i];
+ }
+
+ bool HasShadowWithInset(bool aInset) {
+ for (uint32_t i = 0; i < mLength; ++i) {
+ if (mArray[i].mInset == aInset) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool operator==(const nsCSSShadowArray& aOther) const {
+ if (mLength != aOther.Length()) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < mLength; ++i) {
+ if (ShadowAt(i) != aOther.ShadowAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSShadowArray)
+
+private:
+ uint32_t mLength;
+ nsCSSShadowItem mArray[1]; // This MUST be the last item
+};
+
+// Border widths are rounded to the nearest-below integer number of pixels,
+// but values between zero and one device pixels are always rounded up to
+// one device pixel.
+#define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
+ ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
+// Outline offset is rounded to the nearest integer number of pixels, but values
+// between zero and one device pixels are always rounded up to one device pixel.
+// Note that the offset can be negative.
+#define NS_ROUND_OFFSET_TO_PIXELS(l,tpp) \
+ (((l) == 0) ? 0 : \
+ ((l) > 0) ? std::max( (tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) : \
+ std::min(-(tpp), ((l) - ((tpp) / 2)) / (tpp) * (tpp)))
+
+// Returns if the given border style type is visible or not
+static bool IsVisibleBorderStyle(uint8_t aStyle)
+{
+ return (aStyle != NS_STYLE_BORDER_STYLE_NONE &&
+ aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
+}
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
+{
+ explicit nsStyleBorder(StyleStructContext aContext);
+ nsStyleBorder(const nsStyleBorder& aBorder);
+ ~nsStyleBorder();
+
+ // Resolves and tracks mBorderImageSource. Only called with a Servo-backed
+ // style system, where those images must be resolved later than the OMT
+ // nsStyleBorder constructor call.
+ void FinishStyle(nsPresContext* aPresContext);
+
+ void* operator new(size_t sz, nsStyleBorder* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ nsChangeHint CalcDifference(const nsStyleBorder& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return NS_STYLE_HINT_REFLOW |
+ nsChangeHint_UpdateOverflow |
+ nsChangeHint_BorderStyleNoneChange |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ void EnsureBorderColors() {
+ if (!mBorderColors) {
+ mBorderColors = new nsBorderColors*[4];
+ if (mBorderColors) {
+ for (int32_t i = 0; i < 4; i++) {
+ mBorderColors[i] = nullptr;
+ }
+ }
+ }
+ }
+
+ void ClearBorderColors(mozilla::css::Side aSide) {
+ if (mBorderColors && mBorderColors[aSide]) {
+ delete mBorderColors[aSide];
+ mBorderColors[aSide] = nullptr;
+ }
+ }
+
+ // Return whether aStyle is a visible style. Invisible styles cause
+ // the relevant computed border width to be 0.
+ // Note that this does *not* consider the effects of 'border-image':
+ // if border-style is none, but there is a loaded border image,
+ // HasVisibleStyle will be false even though there *is* a border.
+ bool HasVisibleStyle(mozilla::css::Side aSide) const
+ {
+ return IsVisibleBorderStyle(mBorderStyle[aSide]);
+ }
+
+ // aBorderWidth is in twips
+ void SetBorderWidth(mozilla::css::Side aSide, nscoord aBorderWidth)
+ {
+ nscoord roundedWidth =
+ NS_ROUND_BORDER_TO_PIXELS(aBorderWidth, mTwipsPerPixel);
+ mBorder.Side(aSide) = roundedWidth;
+ if (HasVisibleStyle(aSide)) {
+ mComputedBorder.Side(aSide) = roundedWidth;
+ }
+ }
+
+ // Get the computed border (plus rounding). This does consider the
+ // effects of 'border-style: none', but does not consider
+ // 'border-image'.
+ const nsMargin& GetComputedBorder() const
+ {
+ return mComputedBorder;
+ }
+
+ bool HasBorder() const
+ {
+ return mComputedBorder != nsMargin(0,0,0,0) || !mBorderImageSource.IsEmpty();
+ }
+
+ // Get the actual border width for a particular side, in appunits. Note that
+ // this is zero if and only if there is no border to be painted for this
+ // side. That is, this value takes into account the border style and the
+ // value is rounded to the nearest device pixel by NS_ROUND_BORDER_TO_PIXELS.
+ nscoord GetComputedBorderWidth(mozilla::css::Side aSide) const
+ {
+ return GetComputedBorder().Side(aSide);
+ }
+
+ uint8_t GetBorderStyle(mozilla::css::Side aSide) const
+ {
+ NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
+ return mBorderStyle[aSide];
+ }
+
+ void SetBorderStyle(mozilla::css::Side aSide, uint8_t aStyle)
+ {
+ NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
+ mBorderStyle[aSide] = aStyle;
+ mComputedBorder.Side(aSide) =
+ (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
+ }
+
+ inline bool IsBorderImageLoaded() const
+ {
+ return mBorderImageSource.IsLoaded();
+ }
+
+ void ResolveImage(nsPresContext* aContext)
+ {
+ if (mBorderImageSource.GetType() == eStyleImageType_Image) {
+ mBorderImageSource.ResolveImage(aContext);
+ }
+ }
+
+ nsMargin GetImageOutset() const;
+
+ void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
+ {
+ if (!mBorderColors) {
+ *aColors = nullptr;
+ } else {
+ *aColors = mBorderColors[aIndex];
+ }
+ }
+
+ void AppendBorderColor(int32_t aIndex, nscolor aColor)
+ {
+ NS_ASSERTION(aIndex >= 0 && aIndex <= 3, "bad side for composite border color");
+ nsBorderColors* colorEntry = new nsBorderColors(aColor);
+ if (!mBorderColors[aIndex]) {
+ mBorderColors[aIndex] = colorEntry;
+ } else {
+ nsBorderColors* last = mBorderColors[aIndex];
+ while (last->mNext) {
+ last = last->mNext;
+ }
+ last->mNext = colorEntry;
+ }
+ }
+
+ imgIRequest* GetBorderImageRequest() const
+ {
+ if (mBorderImageSource.GetType() == eStyleImageType_Image) {
+ return mBorderImageSource.GetImageData();
+ }
+ return nullptr;
+ }
+
+public:
+ nsBorderColors** mBorderColors; // [reset] composite (stripe) colors
+ nsStyleCorners mBorderRadius; // [reset] coord, percent
+ nsStyleImage mBorderImageSource; // [reset]
+ nsStyleSides mBorderImageSlice; // [reset] factor, percent
+ nsStyleSides mBorderImageWidth; // [reset] length, factor, percent, auto
+ nsStyleSides mBorderImageOutset; // [reset] length, factor
+
+ uint8_t mBorderImageFill; // [reset]
+ uint8_t mBorderImageRepeatH; // [reset] see nsStyleConsts.h
+ uint8_t mBorderImageRepeatV; // [reset]
+ mozilla::StyleFloatEdge mFloatEdge; // [reset]
+ mozilla::StyleBoxDecorationBreak mBoxDecorationBreak; // [reset]
+
+protected:
+ uint8_t mBorderStyle[4]; // [reset] See nsStyleConsts.h
+
+public:
+ // [reset] the colors to use for a simple border.
+ // not used for -moz-border-colors
+ union {
+ struct {
+ mozilla::StyleComplexColor mBorderTopColor;
+ mozilla::StyleComplexColor mBorderRightColor;
+ mozilla::StyleComplexColor mBorderBottomColor;
+ mozilla::StyleComplexColor mBorderLeftColor;
+ };
+ mozilla::StyleComplexColor mBorderColor[4];
+ };
+
+protected:
+ // mComputedBorder holds the CSS2.1 computed border-width values.
+ // In particular, these widths take into account the border-style
+ // for the relevant side, and the values are rounded to the nearest
+ // device pixel (which is not part of the definition of computed
+ // values). The presence or absence of a border-image does not
+ // affect border-width values.
+ nsMargin mComputedBorder;
+
+ // mBorder holds the nscoord values for the border widths as they
+ // would be if all the border-style values were visible (not hidden
+ // or none). This member exists so that when we create structs
+ // using the copy constructor during style resolution the new
+ // structs will know what the specified values of the border were in
+ // case they have more specific rules setting the border style.
+ //
+ // Note that this isn't quite the CSS specified value, since this
+ // has had the enumerated border widths converted to lengths, and
+ // all lengths converted to twips. But it's not quite the computed
+ // value either. The values are rounded to the nearest device pixel.
+ nsMargin mBorder;
+
+private:
+ nscoord mTwipsPerPixel;
+
+ nsStyleBorder& operator=(const nsStyleBorder& aOther) = delete;
+};
+
+#define ASSERT_BORDER_COLOR_FIELD(side_) \
+ static_assert(offsetof(nsStyleBorder, mBorder##side_##Color) == \
+ offsetof(nsStyleBorder, mBorderColor) + \
+ size_t(mozilla::eSide##side_) * \
+ sizeof(mozilla::StyleComplexColor), \
+ "mBorder" #side_ "Color must be at same offset " \
+ "as mBorderColor[mozilla::eSide" #side_ "]")
+ASSERT_BORDER_COLOR_FIELD(Top);
+ASSERT_BORDER_COLOR_FIELD(Right);
+ASSERT_BORDER_COLOR_FIELD(Bottom);
+ASSERT_BORDER_COLOR_FIELD(Left);
+#undef ASSERT_BORDER_COLOR_FIELD
+
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline
+{
+ explicit nsStyleOutline(StyleStructContext aContext);
+ nsStyleOutline(const nsStyleOutline& aOutline);
+ ~nsStyleOutline() {
+ MOZ_COUNT_DTOR(nsStyleOutline);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleOutline* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleOutline, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleOutline();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleOutline, this);
+ }
+
+ void RecalcData();
+ nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_UpdateOverflow |
+ nsChangeHint_SchedulePaint |
+ nsChangeHint_RepaintFrame |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants at all.
+ return nsChangeHint(0);
+ }
+
+ nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc
+
+ // This is the specified value of outline-width, but with length values
+ // computed to absolute. mActualOutlineWidth stores the outline-width
+ // value used by layout. (We must store mOutlineWidth for the same
+ // style struct resolution reasons that we do nsStyleBorder::mBorder;
+ // see that field's comment.)
+ nsStyleCoord mOutlineWidth; // [reset] coord, enum (see nsStyleConsts.h)
+ nscoord mOutlineOffset; // [reset]
+ mozilla::StyleComplexColor mOutlineColor; // [reset]
+ uint8_t mOutlineStyle; // [reset] See nsStyleConsts.h
+
+ nscoord GetOutlineWidth() const
+ {
+ return mActualOutlineWidth;
+ }
+
+protected:
+ // The actual value of outline-width is the computed value (an absolute
+ // length, forced to zero when outline-style is none) rounded to device
+ // pixels. This is the value used by layout.
+ nscoord mActualOutlineWidth;
+ nscoord mTwipsPerPixel;
+};
+
+
+/**
+ * An object that allows sharing of arrays that store 'quotes' property
+ * values. This is particularly important for inheritance, where we want
+ * to share the same 'quotes' value with a parent style context.
+ */
+class nsStyleQuoteValues
+{
+public:
+ typedef nsTArray<std::pair<nsString, nsString>> QuotePairArray;
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleQuoteValues);
+ QuotePairArray mQuotePairs;
+
+private:
+ ~nsStyleQuoteValues() {}
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
+{
+ explicit nsStyleList(StyleStructContext aContext);
+ nsStyleList(const nsStyleList& aStyleList);
+ ~nsStyleList();
+
+ void FinishStyle(nsPresContext* aPresContext);
+
+ void* operator new(size_t sz, nsStyleList* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleList();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleList, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleList& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ static void Shutdown() {
+ sInitialQuotes = nullptr;
+ sNoneQuotes = nullptr;
+ }
+
+ imgRequestProxy* GetListStyleImage() const
+ {
+ return mListStyleImage ? mListStyleImage->get() : nullptr;
+ }
+
+ void GetListStyleType(nsSubstring& aType) const { mCounterStyle->GetStyleName(aType); }
+ mozilla::CounterStyle* GetCounterStyle() const
+ {
+ return mCounterStyle.get();
+ }
+ void SetCounterStyle(mozilla::CounterStyle* aStyle)
+ {
+ // NB: This function is called off-main-thread during parallel restyle, but
+ // only with builtin styles that use dummy refcounting.
+ MOZ_ASSERT(NS_IsMainThread() || !aStyle->IsDependentStyle());
+ mCounterStyle = aStyle;
+ }
+ void SetListStyleType(const nsSubstring& aType,
+ nsPresContext* aPresContext)
+ {
+ SetCounterStyle(aPresContext->CounterStyleManager()->BuildCounterStyle(aType));
+ }
+
+ const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
+
+ void SetQuotesInherit(const nsStyleList* aOther);
+ void SetQuotesInitial();
+ void SetQuotesNone();
+ void SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues);
+
+ uint8_t mListStylePosition; // [inherited]
+ RefPtr<nsStyleImageRequest> mListStyleImage; // [inherited]
+private:
+ RefPtr<mozilla::CounterStyle> mCounterStyle; // [inherited]
+ RefPtr<nsStyleQuoteValues> mQuotes; // [inherited]
+ nsStyleList& operator=(const nsStyleList& aOther) = delete;
+public:
+ nsRect mImageRegion; // [inherited] the rect to use within an image
+
+private:
+ // nsStyleQuoteValues objects representing two common values, for sharing.
+ static mozilla::StaticRefPtr<nsStyleQuoteValues> sInitialQuotes;
+ static mozilla::StaticRefPtr<nsStyleQuoteValues> sNoneQuotes;
+};
+
+struct nsStyleGridLine
+{
+ // http://dev.w3.org/csswg/css-grid/#typedef-grid-line
+ // XXXmats we could optimize memory size here
+ bool mHasSpan;
+ int32_t mInteger; // 0 means not provided
+ nsString mLineName; // Empty string means not provided.
+
+ // These are the limits that we choose to clamp grid line numbers to.
+ // http://dev.w3.org/csswg/css-grid/#overlarge-grids
+ // mInteger is clamped to this range:
+ static const int32_t kMinLine = -10000;
+ static const int32_t kMaxLine = 10000;
+
+ nsStyleGridLine()
+ : mHasSpan(false)
+ , mInteger(0)
+ // mLineName get its default constructor, the empty string
+ {
+ }
+
+ nsStyleGridLine(const nsStyleGridLine& aOther)
+ {
+ (*this) = aOther;
+ }
+
+ void operator=(const nsStyleGridLine& aOther)
+ {
+ mHasSpan = aOther.mHasSpan;
+ mInteger = aOther.mInteger;
+ mLineName = aOther.mLineName;
+ }
+
+ bool operator!=(const nsStyleGridLine& aOther) const
+ {
+ return mHasSpan != aOther.mHasSpan ||
+ mInteger != aOther.mInteger ||
+ mLineName != aOther.mLineName;
+ }
+
+ void SetToInteger(uint32_t value)
+ {
+ mHasSpan = false;
+ mInteger = value;
+ mLineName.Truncate();
+ }
+
+ void SetAuto()
+ {
+ mHasSpan = false;
+ mInteger = 0;
+ mLineName.Truncate();
+ }
+
+ bool IsAuto() const
+ {
+ bool haveInitialValues = mInteger == 0 && mLineName.IsEmpty();
+ MOZ_ASSERT(!(haveInitialValues && mHasSpan),
+ "should not have 'span' when other components are "
+ "at their initial values");
+ return haveInitialValues;
+ }
+};
+
+// Computed value of the grid-template-columns or grid-template-rows property
+// (but *not* grid-template-areas.)
+// http://dev.w3.org/csswg/css-grid/#track-sizing
+//
+// This represents either:
+// * none:
+// mIsSubgrid is false, all three arrays are empty
+// * <track-list>:
+// mIsSubgrid is false,
+// mMinTrackSizingFunctions and mMaxTrackSizingFunctions
+// are of identical non-zero size,
+// and mLineNameLists is one element longer than that.
+// (Delimiting N columns requires N+1 lines:
+// one before each track, plus one at the very end.)
+//
+// An omitted <line-names> is still represented in mLineNameLists,
+// as an empty sub-array.
+//
+// A <track-size> specified as a single <track-breadth> is represented
+// as identical min and max sizing functions.
+// A 'fit-content(size)' <track-size> is represented as eStyleUnit_None
+// in the min sizing function and 'size' in the max sizing function.
+//
+// The units for nsStyleCoord are:
+// * eStyleUnit_Percent represents a <percentage>
+// * eStyleUnit_FlexFraction represents a <flex> flexible fraction
+// * eStyleUnit_Coord represents a <length>
+// * eStyleUnit_Enumerated represents min-content or max-content
+// * subgrid <line-name-list>?:
+// mIsSubgrid is true,
+// mLineNameLists may or may not be empty,
+// mMinTrackSizingFunctions and mMaxTrackSizingFunctions are empty.
+//
+// If mRepeatAutoIndex != -1 then that index is an <auto-repeat> and
+// mIsAutoFill == true means it's an 'auto-fill', otherwise 'auto-fit'.
+// mRepeatAutoLineNameListBefore is the list of line names before the track
+// size, mRepeatAutoLineNameListAfter the names after. (They are empty
+// when there is no <auto-repeat> track, i.e. when mRepeatAutoIndex == -1).
+// When mIsSubgrid is true, mRepeatAutoLineNameListBefore contains the line
+// names and mRepeatAutoLineNameListAfter is empty.
+struct nsStyleGridTemplate
+{
+ nsTArray<nsTArray<nsString>> mLineNameLists;
+ nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
+ nsTArray<nsStyleCoord> mMaxTrackSizingFunctions;
+ nsTArray<nsString> mRepeatAutoLineNameListBefore;
+ nsTArray<nsString> mRepeatAutoLineNameListAfter;
+ int16_t mRepeatAutoIndex; // -1 or the track index for an auto-fill/fit track
+ bool mIsAutoFill : 1;
+ bool mIsSubgrid : 1;
+
+ nsStyleGridTemplate()
+ : mRepeatAutoIndex(-1)
+ , mIsAutoFill(false)
+ , mIsSubgrid(false)
+ {
+ }
+
+ inline bool operator!=(const nsStyleGridTemplate& aOther) const {
+ return
+ mIsSubgrid != aOther.mIsSubgrid ||
+ mLineNameLists != aOther.mLineNameLists ||
+ mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
+ mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions ||
+ mIsAutoFill != aOther.mIsAutoFill ||
+ mRepeatAutoIndex != aOther.mRepeatAutoIndex ||
+ mRepeatAutoLineNameListBefore != aOther.mRepeatAutoLineNameListBefore ||
+ mRepeatAutoLineNameListAfter != aOther.mRepeatAutoLineNameListAfter;
+ }
+
+ bool HasRepeatAuto() const {
+ return mRepeatAutoIndex != -1;
+ }
+
+ bool IsRepeatAutoIndex(uint32_t aIndex) const {
+ MOZ_ASSERT(aIndex < uint32_t(2*nsStyleGridLine::kMaxLine));
+ return int32_t(aIndex) == mRepeatAutoIndex;
+ }
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
+{
+ explicit nsStylePosition(StyleStructContext aContext);
+ nsStylePosition(const nsStylePosition& aOther);
+ ~nsStylePosition();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStylePosition* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStylePosition();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStylePosition, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStylePosition& aNewData,
+ const nsStyleVisibility* aOldStyleVisibility) const;
+ static nsChangeHint MaxDifference() {
+ return NS_STYLE_HINT_REFLOW |
+ nsChangeHint_NeutralChange |
+ nsChangeHint_RecomputePosition |
+ nsChangeHint_UpdateParentOverflow |
+ nsChangeHint_UpdateComputedBSize;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference can return all of the reflow hints that are
+ // sometimes handled for descendants as hints not handled for
+ // descendants.
+ return nsChangeHint(0);
+ }
+
+ /**
+ * Return the used value for 'align-self' given our parent StyleContext
+ * aParent (or null for the root).
+ */
+ uint8_t UsedAlignSelf(nsStyleContext* aParent) const;
+
+ /**
+ * Return the computed value for 'justify-items' given our parent StyleContext
+ * aParent (or null for the root).
+ */
+ uint8_t ComputedJustifyItems(nsStyleContext* aParent) const;
+
+ /**
+ * Return the used value for 'justify-self' given our parent StyleContext
+ * aParent (or null for the root).
+ */
+ uint8_t UsedJustifySelf(nsStyleContext* aParent) const;
+
+ mozilla::Position mObjectPosition; // [reset]
+ nsStyleSides mOffset; // [reset] coord, percent, calc, auto
+ nsStyleCoord mWidth; // [reset] coord, percent, enum, calc, auto
+ nsStyleCoord mMinWidth; // [reset] coord, percent, enum, calc
+ nsStyleCoord mMaxWidth; // [reset] coord, percent, enum, calc, none
+ nsStyleCoord mHeight; // [reset] coord, percent, calc, auto
+ nsStyleCoord mMinHeight; // [reset] coord, percent, calc
+ nsStyleCoord mMaxHeight; // [reset] coord, percent, calc, none
+ nsStyleCoord mFlexBasis; // [reset] coord, percent, enum, calc, auto
+ nsStyleCoord mGridAutoColumnsMin; // [reset] coord, percent, enum, calc, flex
+ nsStyleCoord mGridAutoColumnsMax; // [reset] coord, percent, enum, calc, flex
+ nsStyleCoord mGridAutoRowsMin; // [reset] coord, percent, enum, calc, flex
+ nsStyleCoord mGridAutoRowsMax; // [reset] coord, percent, enum, calc, flex
+ uint8_t mGridAutoFlow; // [reset] enumerated. See nsStyleConsts.h
+ mozilla::StyleBoxSizing mBoxSizing; // [reset] see nsStyleConsts.h
+
+ uint16_t mAlignContent; // [reset] fallback value in the high byte
+ uint8_t mAlignItems; // [reset] see nsStyleConsts.h
+ uint8_t mAlignSelf; // [reset] see nsStyleConsts.h
+ uint16_t mJustifyContent; // [reset] fallback value in the high byte
+private:
+ friend class nsRuleNode;
+
+ // mJustifyItems should only be read via ComputedJustifyItems(), which
+ // lazily resolves its "auto" value. nsRuleNode needs direct access so
+ // it can set mJustifyItems' value when populating this struct.
+ uint8_t mJustifyItems; // [reset] see nsStyleConsts.h
+public:
+ uint8_t mJustifySelf; // [reset] see nsStyleConsts.h
+ uint8_t mFlexDirection; // [reset] see nsStyleConsts.h
+ uint8_t mFlexWrap; // [reset] see nsStyleConsts.h
+ uint8_t mObjectFit; // [reset] see nsStyleConsts.h
+ int32_t mOrder; // [reset] integer
+ float mFlexGrow; // [reset] float
+ float mFlexShrink; // [reset] float
+ nsStyleCoord mZIndex; // [reset] integer, auto
+ nsStyleGridTemplate mGridTemplateColumns;
+ nsStyleGridTemplate mGridTemplateRows;
+
+ // nullptr for 'none'
+ RefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
+
+ nsStyleGridLine mGridColumnStart;
+ nsStyleGridLine mGridColumnEnd;
+ nsStyleGridLine mGridRowStart;
+ nsStyleGridLine mGridRowEnd;
+ nsStyleCoord mGridColumnGap; // [reset] coord, percent, calc
+ nsStyleCoord mGridRowGap; // [reset] coord, percent, calc
+
+ // FIXME: Logical-coordinate equivalents to these WidthDepends... and
+ // HeightDepends... methods have been introduced (see below); we probably
+ // want to work towards removing the physical methods, and using the logical
+ // ones in all cases.
+
+ bool WidthDependsOnContainer() const
+ {
+ return mWidth.GetUnit() == eStyleUnit_Auto ||
+ WidthCoordDependsOnContainer(mWidth);
+ }
+
+ // NOTE: For a flex item, "min-width:auto" is supposed to behave like
+ // "min-content", which does depend on the container, so you might think we'd
+ // need a special case for "flex item && min-width:auto" here. However,
+ // we don't actually need that special-case code, because flex items are
+ // explicitly supposed to *ignore* their min-width (i.e. behave like it's 0)
+ // until the flex container explicitly considers it. So -- since the flex
+ // container doesn't rely on this method, we don't need to worry about
+ // special behavior for flex items' "min-width:auto" values here.
+ bool MinWidthDependsOnContainer() const
+ { return WidthCoordDependsOnContainer(mMinWidth); }
+ bool MaxWidthDependsOnContainer() const
+ { return WidthCoordDependsOnContainer(mMaxWidth); }
+
+ // Note that these functions count 'auto' as depending on the
+ // container since that's the case for absolutely positioned elements.
+ // However, some callers do not care about this case and should check
+ // for it, since it is the most common case.
+ // FIXME: We should probably change the assumption to be the other way
+ // around.
+ // Consider this as part of moving to the logical-coordinate APIs.
+ bool HeightDependsOnContainer() const
+ {
+ return mHeight.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
+ HeightCoordDependsOnContainer(mHeight);
+ }
+
+ // NOTE: The comment above MinWidthDependsOnContainer about flex items
+ // applies here, too.
+ bool MinHeightDependsOnContainer() const
+ { return HeightCoordDependsOnContainer(mMinHeight); }
+ bool MaxHeightDependsOnContainer() const
+ { return HeightCoordDependsOnContainer(mMaxHeight); }
+
+ bool OffsetHasPercent(mozilla::css::Side aSide) const
+ {
+ return mOffset.Get(aSide).HasPercent();
+ }
+
+ // Logical-coordinate accessors for width and height properties,
+ // given a WritingMode value. The definitions of these methods are
+ // found in WritingModes.h (after the WritingMode class is fully
+ // declared).
+ inline nsStyleCoord& ISize(mozilla::WritingMode aWM);
+ inline nsStyleCoord& MinISize(mozilla::WritingMode aWM);
+ inline nsStyleCoord& MaxISize(mozilla::WritingMode aWM);
+ inline nsStyleCoord& BSize(mozilla::WritingMode aWM);
+ inline nsStyleCoord& MinBSize(mozilla::WritingMode aWM);
+ inline nsStyleCoord& MaxBSize(mozilla::WritingMode aWM);
+ inline const nsStyleCoord& ISize(mozilla::WritingMode aWM) const;
+ inline const nsStyleCoord& MinISize(mozilla::WritingMode aWM) const;
+ inline const nsStyleCoord& MaxISize(mozilla::WritingMode aWM) const;
+ inline const nsStyleCoord& BSize(mozilla::WritingMode aWM) const;
+ inline const nsStyleCoord& MinBSize(mozilla::WritingMode aWM) const;
+ inline const nsStyleCoord& MaxBSize(mozilla::WritingMode aWM) const;
+ inline bool ISizeDependsOnContainer(mozilla::WritingMode aWM) const;
+ inline bool MinISizeDependsOnContainer(mozilla::WritingMode aWM) const;
+ inline bool MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const;
+ inline bool BSizeDependsOnContainer(mozilla::WritingMode aWM) const;
+ inline bool MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
+ inline bool MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
+
+private:
+ static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
+ static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
+ { return aCoord.HasPercent(); }
+};
+
+struct nsStyleTextOverflowSide
+{
+ nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
+
+ bool operator==(const nsStyleTextOverflowSide& aOther) const {
+ return mType == aOther.mType &&
+ (mType != NS_STYLE_TEXT_OVERFLOW_STRING ||
+ mString == aOther.mString);
+ }
+ bool operator!=(const nsStyleTextOverflowSide& aOther) const {
+ return !(*this == aOther);
+ }
+
+ nsString mString;
+ uint8_t mType;
+};
+
+struct nsStyleTextOverflow
+{
+ nsStyleTextOverflow() : mLogicalDirections(true) {}
+ bool operator==(const nsStyleTextOverflow& aOther) const {
+ return mLeft == aOther.mLeft && mRight == aOther.mRight;
+ }
+ bool operator!=(const nsStyleTextOverflow& aOther) const {
+ return !(*this == aOther);
+ }
+
+ // Returns the value to apply on the left side.
+ const nsStyleTextOverflowSide& GetLeft(uint8_t aDirection) const {
+ NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
+ aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
+ return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
+ mLeft : mRight;
+ }
+
+ // Returns the value to apply on the right side.
+ const nsStyleTextOverflowSide& GetRight(uint8_t aDirection) const {
+ NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
+ aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
+ return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
+ mRight : mLeft;
+ }
+
+ // Returns the first value that was specified.
+ const nsStyleTextOverflowSide* GetFirstValue() const {
+ return mLogicalDirections ? &mRight : &mLeft;
+ }
+
+ // Returns the second value, or null if there was only one value specified.
+ const nsStyleTextOverflowSide* GetSecondValue() const {
+ return mLogicalDirections ? nullptr : &mRight;
+ }
+
+ nsStyleTextOverflowSide mLeft; // start side when mLogicalDirections is true
+ nsStyleTextOverflowSide mRight; // end side when mLogicalDirections is true
+ bool mLogicalDirections; // true when only one value was specified
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset
+{
+ explicit nsStyleTextReset(StyleStructContext aContext);
+ nsStyleTextReset(const nsStyleTextReset& aOther);
+ ~nsStyleTextReset();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleTextReset* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleTextReset();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, this);
+ }
+
+ // Note the difference between this and
+ // nsStyleContext::HasTextDecorationLines.
+ bool HasTextDecorationLines() const {
+ return mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_NONE &&
+ mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
+ }
+
+ nsChangeHint CalcDifference(const nsStyleTextReset& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint(
+ NS_STYLE_HINT_REFLOW |
+ nsChangeHint_UpdateSubtreeOverflow);
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ nsStyleTextOverflow mTextOverflow; // [reset] enum, string
+
+ uint8_t mTextDecorationLine; // [reset] see nsStyleConsts.h
+ uint8_t mTextDecorationStyle; // [reset] see nsStyleConsts.h
+ uint8_t mUnicodeBidi; // [reset] see nsStyleConsts.h
+ nscoord mInitialLetterSink; // [reset] 0 means normal
+ float mInitialLetterSize; // [reset] 0.0f means normal
+ mozilla::StyleComplexColor mTextDecorationColor; // [reset]
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
+{
+ explicit nsStyleText(StyleStructContext aContext);
+ nsStyleText(const nsStyleText& aOther);
+ ~nsStyleText();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleText* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleText();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleText, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleText& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW |
+ nsChangeHint_UpdateSubtreeOverflow |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ uint8_t mTextAlign; // [inherited] see nsStyleConsts.h
+ uint8_t mTextAlignLast; // [inherited] see nsStyleConsts.h
+ bool mTextAlignTrue : 1; // [inherited] see nsStyleConsts.h
+ bool mTextAlignLastTrue : 1; // [inherited] see nsStyleConsts.h
+ uint8_t mTextTransform; // [inherited] see nsStyleConsts.h
+ uint8_t mWhiteSpace; // [inherited] see nsStyleConsts.h
+ uint8_t mWordBreak; // [inherited] see nsStyleConsts.h
+ uint8_t mOverflowWrap; // [inherited] see nsStyleConsts.h
+ uint8_t mHyphens; // [inherited] see nsStyleConsts.h
+ uint8_t mRubyAlign; // [inherited] see nsStyleConsts.h
+ uint8_t mRubyPosition; // [inherited] see nsStyleConsts.h
+ uint8_t mTextSizeAdjust; // [inherited] see nsStyleConsts.h
+ uint8_t mTextCombineUpright; // [inherited] see nsStyleConsts.h
+ uint8_t mControlCharacterVisibility; // [inherited] see nsStyleConsts.h
+ uint8_t mTextEmphasisPosition; // [inherited] see nsStyleConsts.h
+ uint8_t mTextEmphasisStyle; // [inherited] see nsStyleConsts.h
+ uint8_t mTextRendering; // [inherited] see nsStyleConsts.h
+ int32_t mTabSize; // [inherited] see nsStyleConsts.h
+ mozilla::StyleComplexColor mTextEmphasisColor; // [inherited]
+ mozilla::StyleComplexColor mWebkitTextFillColor; // [inherited]
+ mozilla::StyleComplexColor mWebkitTextStrokeColor; // [inherited]
+
+ nsStyleCoord mWordSpacing; // [inherited] coord, percent, calc
+ nsStyleCoord mLetterSpacing; // [inherited] coord, normal
+ nsStyleCoord mLineHeight; // [inherited] coord, factor, normal
+ nsStyleCoord mTextIndent; // [inherited] coord, percent, calc
+ nsStyleCoord mWebkitTextStrokeWidth; // [inherited] coord
+
+ RefPtr<nsCSSShadowArray> mTextShadow; // [inherited] nullptr in case of a zero-length
+
+ nsString mTextEmphasisStyleString; // [inherited]
+
+ bool WhiteSpaceIsSignificant() const {
+ return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
+ }
+
+ bool NewlineIsSignificantStyle() const {
+ return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
+ }
+
+ bool WhiteSpaceOrNewlineIsSignificant() const {
+ return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
+ }
+
+ bool TabIsSignificant() const {
+ return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
+ }
+
+ bool WhiteSpaceCanWrapStyle() const {
+ return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
+ mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
+ }
+
+ bool WordCanWrapStyle() const {
+ return WhiteSpaceCanWrapStyle() &&
+ mOverflowWrap == NS_STYLE_OVERFLOWWRAP_BREAK_WORD;
+ }
+
+ bool HasTextEmphasis() const {
+ return !mTextEmphasisStyleString.IsEmpty();
+ }
+
+ bool HasWebkitTextStroke() const {
+ return mWebkitTextStrokeWidth.GetCoordValue() > 0;
+ }
+
+ // These are defined in nsStyleStructInlines.h.
+ inline bool HasTextShadow() const;
+ inline nsCSSShadowArray* GetTextShadow() const;
+
+ // The aContextFrame argument on each of these is the frame this
+ // style struct is for. If the frame is for SVG text or inside ruby,
+ // the return value will be massaged to be something that makes sense
+ // for those cases.
+ inline bool NewlineIsSignificant(const nsTextFrame* aContextFrame) const;
+ inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
+ inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
+
+ mozilla::LogicalSide TextEmphasisSide(mozilla::WritingMode aWM) const;
+};
+
+struct nsStyleImageOrientation
+{
+ static nsStyleImageOrientation CreateAsAngleAndFlip(double aRadians,
+ bool aFlip) {
+ uint8_t orientation(0);
+
+ // Compute the final angle value, rounding to the closest quarter turn.
+ double roundedAngle = fmod(aRadians, 2 * M_PI);
+ if (roundedAngle < 0.25 * M_PI) { orientation = ANGLE_0; }
+ else if (roundedAngle < 0.75 * M_PI) { orientation = ANGLE_90; }
+ else if (roundedAngle < 1.25 * M_PI) { orientation = ANGLE_180;}
+ else if (roundedAngle < 1.75 * M_PI) { orientation = ANGLE_270;}
+ else { orientation = ANGLE_0; }
+
+ // Add a bit for 'flip' if needed.
+ if (aFlip) {
+ orientation |= FLIP_MASK;
+ }
+
+ return nsStyleImageOrientation(orientation);
+ }
+
+ static nsStyleImageOrientation CreateAsFlip() {
+ return nsStyleImageOrientation(FLIP_MASK);
+ }
+
+ static nsStyleImageOrientation CreateAsFromImage() {
+ return nsStyleImageOrientation(FROM_IMAGE_MASK);
+ }
+
+ // The default constructor yields 0 degrees of rotation and no flip.
+ nsStyleImageOrientation() : mOrientation(0) { }
+
+ bool IsDefault() const { return mOrientation == 0; }
+ bool IsFlipped() const { return mOrientation & FLIP_MASK; }
+ bool IsFromImage() const { return mOrientation & FROM_IMAGE_MASK; }
+ bool SwapsWidthAndHeight() const {
+ uint8_t angle = mOrientation & ORIENTATION_MASK;
+ return (angle == ANGLE_90) || (angle == ANGLE_270);
+ }
+
+ mozilla::image::Angle Angle() const {
+ switch (mOrientation & ORIENTATION_MASK) {
+ case ANGLE_0: return mozilla::image::Angle::D0;
+ case ANGLE_90: return mozilla::image::Angle::D90;
+ case ANGLE_180: return mozilla::image::Angle::D180;
+ case ANGLE_270: return mozilla::image::Angle::D270;
+ default:
+ NS_NOTREACHED("Unexpected angle");
+ return mozilla::image::Angle::D0;
+ }
+ }
+
+ nsStyleCoord AngleAsCoord() const {
+ switch (mOrientation & ORIENTATION_MASK) {
+ case ANGLE_0: return nsStyleCoord(0.0f, eStyleUnit_Degree);
+ case ANGLE_90: return nsStyleCoord(90.0f, eStyleUnit_Degree);
+ case ANGLE_180: return nsStyleCoord(180.0f, eStyleUnit_Degree);
+ case ANGLE_270: return nsStyleCoord(270.0f, eStyleUnit_Degree);
+ default:
+ NS_NOTREACHED("Unexpected angle");
+ return nsStyleCoord();
+ }
+ }
+
+ bool operator==(const nsStyleImageOrientation& aOther) const {
+ return aOther.mOrientation == mOrientation;
+ }
+
+ bool operator!=(const nsStyleImageOrientation& aOther) const {
+ return !(*this == aOther);
+ }
+
+protected:
+ enum Bits {
+ ORIENTATION_MASK = 0x1 | 0x2, // The bottom two bits are the angle.
+ FLIP_MASK = 0x4, // Whether the image should be flipped.
+ FROM_IMAGE_MASK = 0x8, // Whether the image's inherent orientation
+ }; // should be used.
+
+ enum Angles {
+ ANGLE_0 = 0,
+ ANGLE_90 = 1,
+ ANGLE_180 = 2,
+ ANGLE_270 = 3,
+ };
+
+ explicit nsStyleImageOrientation(uint8_t aOrientation)
+ : mOrientation(aOrientation)
+ { }
+
+ uint8_t mOrientation;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility
+{
+ explicit nsStyleVisibility(StyleStructContext aContext);
+ nsStyleVisibility(const nsStyleVisibility& aVisibility);
+ ~nsStyleVisibility() {
+ MOZ_COUNT_DTOR(nsStyleVisibility);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleVisibility* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleVisibility();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleVisibility& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ nsStyleImageOrientation mImageOrientation; // [inherited]
+ uint8_t mDirection; // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
+ uint8_t mVisible; // [inherited]
+ uint8_t mImageRendering; // [inherited] see nsStyleConsts.h
+ uint8_t mWritingMode; // [inherited] see nsStyleConsts.h
+ uint8_t mTextOrientation; // [inherited] see nsStyleConsts.h
+ uint8_t mColorAdjust; // [inherited] see nsStyleConsts.h
+
+ bool IsVisible() const {
+ return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
+ }
+
+ bool IsVisibleOrCollapsed() const {
+ return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
+ (mVisible == NS_STYLE_VISIBILITY_COLLAPSE));
+ }
+};
+
+struct nsTimingFunction
+{
+
+ enum class Type {
+ Ease, // ease
+ Linear, // linear
+ EaseIn, // ease-in
+ EaseOut, // ease-out
+ EaseInOut, // ease-in-out
+ StepStart, // step-start and steps(..., start)
+ StepEnd, // step-end, steps(..., end) and steps(...)
+ CubicBezier, // cubic-bezier()
+ };
+
+ // Whether the timing function type is represented by a spline,
+ // and thus will have mFunc filled in.
+ static bool IsSplineType(Type aType)
+ {
+ return aType != Type::StepStart && aType != Type::StepEnd;
+ }
+
+ explicit nsTimingFunction(int32_t aTimingFunctionType
+ = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)
+ {
+ AssignFromKeyword(aTimingFunctionType);
+ }
+
+ nsTimingFunction(float x1, float y1, float x2, float y2)
+ : mType(Type::CubicBezier)
+ {
+ mFunc.mX1 = x1;
+ mFunc.mY1 = y1;
+ mFunc.mX2 = x2;
+ mFunc.mY2 = y2;
+ }
+
+ enum class Keyword { Implicit, Explicit };
+
+ nsTimingFunction(Type aType, uint32_t aSteps)
+ : mType(aType)
+ {
+ MOZ_ASSERT(mType == Type::StepStart || mType == Type::StepEnd,
+ "wrong type");
+ mSteps = aSteps;
+ }
+
+ nsTimingFunction(const nsTimingFunction& aOther)
+ {
+ *this = aOther;
+ }
+
+ Type mType;
+ union {
+ struct {
+ float mX1;
+ float mY1;
+ float mX2;
+ float mY2;
+ } mFunc;
+ struct {
+ uint32_t mSteps;
+ };
+ };
+
+ nsTimingFunction&
+ operator=(const nsTimingFunction& aOther)
+ {
+ if (&aOther == this) {
+ return *this;
+ }
+
+ mType = aOther.mType;
+
+ if (HasSpline()) {
+ mFunc.mX1 = aOther.mFunc.mX1;
+ mFunc.mY1 = aOther.mFunc.mY1;
+ mFunc.mX2 = aOther.mFunc.mX2;
+ mFunc.mY2 = aOther.mFunc.mY2;
+ } else {
+ mSteps = aOther.mSteps;
+ }
+
+ return *this;
+ }
+
+ bool operator==(const nsTimingFunction& aOther) const
+ {
+ if (mType != aOther.mType) {
+ return false;
+ }
+ if (HasSpline()) {
+ return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
+ mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
+ }
+ return mSteps == aOther.mSteps;
+ }
+
+ bool operator!=(const nsTimingFunction& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ bool HasSpline() const { return IsSplineType(mType); }
+
+private:
+ void AssignFromKeyword(int32_t aTimingFunctionType);
+};
+
+namespace mozilla {
+
+struct StyleTransition
+{
+ StyleTransition() { /* leaves uninitialized; see also SetInitialValues */ }
+ explicit StyleTransition(const StyleTransition& aCopy);
+
+ void SetInitialValues();
+
+ // Delay and Duration are in milliseconds
+
+ const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
+ float GetDelay() const { return mDelay; }
+ float GetDuration() const { return mDuration; }
+ nsCSSPropertyID GetProperty() const { return mProperty; }
+ nsIAtom* GetUnknownProperty() const { return mUnknownProperty; }
+
+ float GetCombinedDuration() const {
+ // http://dev.w3.org/csswg/css-transitions/#combined-duration
+ return std::max(mDuration, 0.0f) + mDelay;
+ }
+
+ void SetTimingFunction(const nsTimingFunction& aTimingFunction)
+ { mTimingFunction = aTimingFunction; }
+ void SetDelay(float aDelay) { mDelay = aDelay; }
+ void SetDuration(float aDuration) { mDuration = aDuration; }
+ void SetProperty(nsCSSPropertyID aProperty)
+ {
+ NS_ASSERTION(aProperty != eCSSProperty_UNKNOWN &&
+ aProperty != eCSSPropertyExtra_variable,
+ "invalid property");
+ mProperty = aProperty;
+ }
+ void SetUnknownProperty(nsCSSPropertyID aProperty,
+ const nsAString& aPropertyString);
+ void CopyPropertyFrom(const StyleTransition& aOther)
+ {
+ mProperty = aOther.mProperty;
+ mUnknownProperty = aOther.mUnknownProperty;
+ }
+
+ nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
+
+ bool operator==(const StyleTransition& aOther) const;
+ bool operator!=(const StyleTransition& aOther) const
+ { return !(*this == aOther); }
+
+private:
+ nsTimingFunction mTimingFunction;
+ float mDuration;
+ float mDelay;
+ nsCSSPropertyID mProperty;
+ nsCOMPtr<nsIAtom> mUnknownProperty; // used when mProperty is
+ // eCSSProperty_UNKNOWN or
+ // eCSSPropertyExtra_variable
+};
+
+struct StyleAnimation
+{
+ StyleAnimation() { /* leaves uninitialized; see also SetInitialValues */ }
+ explicit StyleAnimation(const StyleAnimation& aCopy);
+
+ void SetInitialValues();
+
+ // Delay and Duration are in milliseconds
+
+ const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
+ float GetDelay() const { return mDelay; }
+ float GetDuration() const { return mDuration; }
+ const nsString& GetName() const { return mName; }
+ dom::PlaybackDirection GetDirection() const { return mDirection; }
+ dom::FillMode GetFillMode() const { return mFillMode; }
+ uint8_t GetPlayState() const { return mPlayState; }
+ float GetIterationCount() const { return mIterationCount; }
+
+ void SetTimingFunction(const nsTimingFunction& aTimingFunction)
+ { mTimingFunction = aTimingFunction; }
+ void SetDelay(float aDelay) { mDelay = aDelay; }
+ void SetDuration(float aDuration) { mDuration = aDuration; }
+ void SetName(const nsSubstring& aName) { mName = aName; }
+ void SetDirection(dom::PlaybackDirection aDirection) { mDirection = aDirection; }
+ void SetFillMode(dom::FillMode aFillMode) { mFillMode = aFillMode; }
+ void SetPlayState(uint8_t aPlayState) { mPlayState = aPlayState; }
+ void SetIterationCount(float aIterationCount)
+ { mIterationCount = aIterationCount; }
+
+ nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
+
+ bool operator==(const StyleAnimation& aOther) const;
+ bool operator!=(const StyleAnimation& aOther) const
+ { return !(*this == aOther); }
+
+private:
+ nsTimingFunction mTimingFunction;
+ float mDuration;
+ float mDelay;
+ nsString mName; // empty string for 'none'
+ dom::PlaybackDirection mDirection;
+ dom::FillMode mFillMode;
+ uint8_t mPlayState;
+ float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
+};
+
+class StyleBasicShape final
+{
+public:
+ explicit StyleBasicShape(StyleBasicShapeType type)
+ : mType(type),
+ mFillRule(StyleFillRule::Nonzero)
+ {
+ mPosition.SetInitialPercentValues(0.5f);
+ }
+
+ StyleBasicShapeType GetShapeType() const { return mType; }
+ nsCSSKeyword GetShapeTypeName() const;
+
+ StyleFillRule GetFillRule() const { return mFillRule; }
+ void SetFillRule(StyleFillRule aFillRule)
+ {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Polygon, "expected polygon");
+ mFillRule = aFillRule;
+ }
+
+ Position& GetPosition() {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
+ mType == StyleBasicShapeType::Ellipse,
+ "expected circle or ellipse");
+ return mPosition;
+ }
+ const Position& GetPosition() const {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
+ mType == StyleBasicShapeType::Ellipse,
+ "expected circle or ellipse");
+ return mPosition;
+ }
+
+ bool HasRadius() const {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
+ nsStyleCoord zero;
+ zero.SetCoordValue(0);
+ NS_FOR_CSS_HALF_CORNERS(corner) {
+ if (mRadius.Get(corner) != zero) {
+ return true;
+ }
+ }
+ return false;
+ }
+ nsStyleCorners& GetRadius() {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
+ return mRadius;
+ }
+ const nsStyleCorners& GetRadius() const {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
+ return mRadius;
+ }
+
+ // mCoordinates has coordinates for polygon or radii for
+ // ellipse and circle.
+ nsTArray<nsStyleCoord>& Coordinates()
+ {
+ return mCoordinates;
+ }
+
+ const nsTArray<nsStyleCoord>& Coordinates() const
+ {
+ return mCoordinates;
+ }
+
+ bool operator==(const StyleBasicShape& aOther) const
+ {
+ return mType == aOther.mType &&
+ mFillRule == aOther.mFillRule &&
+ mCoordinates == aOther.mCoordinates &&
+ mPosition == aOther.mPosition &&
+ mRadius == aOther.mRadius;
+ }
+ bool operator!=(const StyleBasicShape& aOther) const {
+ return !(*this == aOther);
+ }
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StyleBasicShape);
+
+private:
+ ~StyleBasicShape() {}
+
+ StyleBasicShapeType mType;
+ StyleFillRule mFillRule;
+
+ // mCoordinates has coordinates for polygon or radii for
+ // ellipse and circle.
+ // (top, right, bottom, left) for inset
+ nsTArray<nsStyleCoord> mCoordinates;
+ // position of center for ellipse or circle
+ Position mPosition;
+ // corner radii for inset (0 if not set)
+ nsStyleCorners mRadius;
+};
+
+template<typename ReferenceBox>
+struct StyleShapeSource
+{
+ StyleShapeSource()
+ : mURL(nullptr)
+ {}
+
+ StyleShapeSource(const StyleShapeSource& aSource)
+ : StyleShapeSource()
+ {
+ if (aSource.mType == StyleShapeSourceType::URL) {
+ SetURL(aSource.mURL);
+ } else if (aSource.mType == StyleShapeSourceType::Shape) {
+ SetBasicShape(aSource.mBasicShape, aSource.mReferenceBox);
+ } else if (aSource.mType == StyleShapeSourceType::Box) {
+ SetReferenceBox(aSource.mReferenceBox);
+ }
+ }
+
+ ~StyleShapeSource()
+ {
+ ReleaseRef();
+ }
+
+ StyleShapeSource& operator=(const StyleShapeSource& aOther)
+ {
+ if (this == &aOther) {
+ return *this;
+ }
+
+ if (aOther.mType == StyleShapeSourceType::URL) {
+ SetURL(aOther.mURL);
+ } else if (aOther.mType == StyleShapeSourceType::Shape) {
+ SetBasicShape(aOther.mBasicShape, aOther.mReferenceBox);
+ } else if (aOther.mType == StyleShapeSourceType::Box) {
+ SetReferenceBox(aOther.mReferenceBox);
+ } else {
+ ReleaseRef();
+ mReferenceBox = ReferenceBox::NoBox;
+ mType = StyleShapeSourceType::None;
+ }
+ return *this;
+ }
+
+ bool operator==(const StyleShapeSource& aOther) const
+ {
+ if (mType != aOther.mType) {
+ return false;
+ }
+
+ if (mType == StyleShapeSourceType::URL) {
+ return mURL->Equals(*aOther.mURL);
+ } else if (mType == StyleShapeSourceType::Shape) {
+ return *mBasicShape == *aOther.mBasicShape &&
+ mReferenceBox == aOther.mReferenceBox;
+ } else if (mType == StyleShapeSourceType::Box) {
+ return mReferenceBox == aOther.mReferenceBox;
+ }
+
+ return true;
+ }
+
+ bool operator!=(const StyleShapeSource& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ StyleShapeSourceType GetType() const
+ {
+ return mType;
+ }
+
+ css::URLValue* GetURL() const
+ {
+ MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
+ return mURL;
+ }
+
+ bool SetURL(css::URLValue* aValue)
+ {
+ MOZ_ASSERT(aValue);
+ ReleaseRef();
+ mURL = aValue;
+ mURL->AddRef();
+ mType = StyleShapeSourceType::URL;
+ return true;
+ }
+
+ StyleBasicShape* GetBasicShape() const
+ {
+ MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
+ return mBasicShape;
+ }
+
+ void SetBasicShape(StyleBasicShape* aBasicShape,
+ ReferenceBox aReferenceBox)
+ {
+ NS_ASSERTION(aBasicShape, "expected pointer");
+ ReleaseRef();
+ mBasicShape = aBasicShape;
+ mBasicShape->AddRef();
+ mReferenceBox = aReferenceBox;
+ mType = StyleShapeSourceType::Shape;
+ }
+
+ ReferenceBox GetReferenceBox() const
+ {
+ MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
+ mType == StyleShapeSourceType::Shape,
+ "Wrong shape source type!");
+ return mReferenceBox;
+ }
+
+ void SetReferenceBox(ReferenceBox aReferenceBox)
+ {
+ ReleaseRef();
+ mReferenceBox = aReferenceBox;
+ mType = StyleShapeSourceType::Box;
+ }
+
+private:
+ void ReleaseRef()
+ {
+ if (mType == StyleShapeSourceType::Shape) {
+ NS_ASSERTION(mBasicShape, "expected pointer");
+ mBasicShape->Release();
+ } else if (mType == StyleShapeSourceType::URL) {
+ NS_ASSERTION(mURL, "expected pointer");
+ mURL->Release();
+ }
+ // Both mBasicShape and mURL are pointers in a union. Nulling one of them
+ // nulls both of them.
+ mURL = nullptr;
+ }
+
+ void* operator new(size_t) = delete;
+
+ union {
+ StyleBasicShape* mBasicShape;
+ css::URLValue* mURL;
+ };
+ StyleShapeSourceType mType = StyleShapeSourceType::None;
+ ReferenceBox mReferenceBox = ReferenceBox::NoBox;
+};
+
+using StyleClipPath = StyleShapeSource<StyleClipPathGeometryBox>;
+using StyleShapeOutside = StyleShapeSource<StyleShapeOutsideShapeBox>;
+
+} // namespace mozilla
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
+{
+ explicit nsStyleDisplay(StyleStructContext aContext);
+ nsStyleDisplay(const nsStyleDisplay& aOther);
+ ~nsStyleDisplay() {
+ MOZ_COUNT_DTOR(nsStyleDisplay);
+ }
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleDisplay* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleDisplay();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleDisplay& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ // All the parts of FRAMECHANGE are present in CalcDifference.
+ return nsChangeHint(nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW |
+ nsChangeHint_UpdateTransformLayer |
+ nsChangeHint_UpdateOverflow |
+ nsChangeHint_UpdatePostTransformOverflow |
+ nsChangeHint_UpdateContainingBlock |
+ nsChangeHint_AddOrRemoveTransform |
+ nsChangeHint_NeutralChange);
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference can return all of the reflow hints that are
+ // sometimes handled for descendants as hints not handled for
+ // descendants.
+ return nsChangeHint(0);
+ }
+
+ // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
+ // mBinding->mOriginPrincipal.
+ RefPtr<mozilla::css::URLValue> mBinding; // [reset]
+ mozilla::StyleDisplay mDisplay; // [reset] see nsStyleConsts.h SyleDisplay
+ mozilla::StyleDisplay mOriginalDisplay; // [reset] saved mDisplay for
+ // position:absolute/fixed
+ // and float:left/right;
+ // otherwise equal to
+ // mDisplay
+ uint8_t mContain; // [reset] see nsStyleConsts.h NS_STYLE_CONTAIN_*
+ uint8_t mAppearance; // [reset]
+ uint8_t mPosition; // [reset] see nsStyleConsts.h
+
+ // [reset] See StyleFloat in nsStyleConsts.h.
+ mozilla::StyleFloat mFloat;
+ // [reset] Save mFloat for position:absolute/fixed; otherwise equal to mFloat.
+ mozilla::StyleFloat mOriginalFloat;
+
+ mozilla::StyleClear mBreakType; // [reset]
+ uint8_t mBreakInside; // [reset] NS_STYLE_PAGE_BREAK_AUTO/AVOID
+ bool mBreakBefore; // [reset]
+ bool mBreakAfter; // [reset]
+ uint8_t mOverflowX; // [reset] see nsStyleConsts.h
+ uint8_t mOverflowY; // [reset] see nsStyleConsts.h
+ uint8_t mOverflowClipBox; // [reset] see nsStyleConsts.h
+ uint8_t mResize; // [reset] see nsStyleConsts.h
+ mozilla::StyleOrient mOrient; // [reset] see nsStyleConsts.h
+ uint8_t mIsolation; // [reset] see nsStyleConsts.h
+ uint8_t mTopLayer; // [reset] see nsStyleConsts.h
+ uint8_t mWillChangeBitField; // [reset] see nsStyleConsts.h. Stores a
+ // bitfield representation of the properties
+ // that are frequently queried. This should
+ // match mWillChange. Also tracks if any of the
+ // properties in the will-change list require
+ // a stacking context.
+ nsTArray<nsString> mWillChange;
+
+ uint8_t mTouchAction; // [reset] see nsStyleConsts.h
+ uint8_t mScrollBehavior; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_BEHAVIOR_*
+ uint8_t mScrollSnapTypeX; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_SNAP_TYPE_*
+ uint8_t mScrollSnapTypeY; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_SNAP_TYPE_*
+ nsStyleCoord mScrollSnapPointsX; // [reset]
+ nsStyleCoord mScrollSnapPointsY; // [reset]
+ mozilla::Position mScrollSnapDestination; // [reset]
+ nsTArray<mozilla::Position> mScrollSnapCoordinate; // [reset]
+
+ // mSpecifiedTransform is the list of transform functions as
+ // specified, or null to indicate there is no transform. (inherit or
+ // initial are replaced by an actual list of transform functions, or
+ // null, as appropriate.)
+ uint8_t mBackfaceVisibility;
+ uint8_t mTransformStyle;
+ uint8_t mTransformBox; // [reset] see nsStyleConsts.h
+ RefPtr<nsCSSValueSharedList> mSpecifiedTransform; // [reset]
+ nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
+ nsStyleCoord mChildPerspective; // [reset] none, coord
+ nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
+
+ nsStyleCoord mVerticalAlign; // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
+
+ nsStyleAutoArray<mozilla::StyleTransition> mTransitions; // [reset]
+
+ // The number of elements in mTransitions that are not from repeating
+ // a list due to another property being longer.
+ uint32_t mTransitionTimingFunctionCount,
+ mTransitionDurationCount,
+ mTransitionDelayCount,
+ mTransitionPropertyCount;
+
+ nsStyleAutoArray<mozilla::StyleAnimation> mAnimations; // [reset]
+
+ // The number of elements in mAnimations that are not from repeating
+ // a list due to another property being longer.
+ uint32_t mAnimationTimingFunctionCount,
+ mAnimationDurationCount,
+ mAnimationDelayCount,
+ mAnimationNameCount,
+ mAnimationDirectionCount,
+ mAnimationFillModeCount,
+ mAnimationPlayStateCount,
+ mAnimationIterationCountCount;
+
+ mozilla::StyleShapeOutside mShapeOutside; // [reset]
+
+ bool IsBlockInsideStyle() const {
+ return mozilla::StyleDisplay::Block == mDisplay ||
+ mozilla::StyleDisplay::ListItem == mDisplay ||
+ mozilla::StyleDisplay::InlineBlock == mDisplay ||
+ mozilla::StyleDisplay::TableCaption == mDisplay;
+ // Should TABLE_CELL be included here? They have
+ // block frames nested inside of them.
+ // (But please audit all callers before changing.)
+ }
+
+ bool IsBlockOutsideStyle() const {
+ return mozilla::StyleDisplay::Block == mDisplay ||
+ mozilla::StyleDisplay::Flex == mDisplay ||
+ mozilla::StyleDisplay::WebkitBox == mDisplay ||
+ mozilla::StyleDisplay::Grid == mDisplay ||
+ mozilla::StyleDisplay::ListItem == mDisplay ||
+ mozilla::StyleDisplay::Table == mDisplay;
+ }
+
+ static bool IsDisplayTypeInlineOutside(mozilla::StyleDisplay aDisplay) {
+ return mozilla::StyleDisplay::Inline == aDisplay ||
+ mozilla::StyleDisplay::InlineBlock == aDisplay ||
+ mozilla::StyleDisplay::InlineTable == aDisplay ||
+ mozilla::StyleDisplay::InlineBox == aDisplay ||
+ mozilla::StyleDisplay::InlineFlex == aDisplay ||
+ mozilla::StyleDisplay::WebkitInlineBox == aDisplay ||
+ mozilla::StyleDisplay::InlineGrid == aDisplay ||
+ mozilla::StyleDisplay::InlineXulGrid == aDisplay ||
+ mozilla::StyleDisplay::InlineStack == aDisplay ||
+ mozilla::StyleDisplay::Ruby == aDisplay ||
+ mozilla::StyleDisplay::RubyBase == aDisplay ||
+ mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||
+ mozilla::StyleDisplay::RubyText == aDisplay ||
+ mozilla::StyleDisplay::RubyTextContainer == aDisplay ||
+ mozilla::StyleDisplay::Contents == aDisplay;
+ }
+
+ bool IsInlineOutsideStyle() const {
+ return IsDisplayTypeInlineOutside(mDisplay);
+ }
+
+ bool IsOriginalDisplayInlineOutsideStyle() const {
+ return IsDisplayTypeInlineOutside(mOriginalDisplay);
+ }
+
+ bool IsInnerTableStyle() const {
+ return mozilla::StyleDisplay::TableCaption == mDisplay ||
+ mozilla::StyleDisplay::TableCell == mDisplay ||
+ mozilla::StyleDisplay::TableRow == mDisplay ||
+ mozilla::StyleDisplay::TableRowGroup == mDisplay ||
+ mozilla::StyleDisplay::TableHeaderGroup == mDisplay ||
+ mozilla::StyleDisplay::TableFooterGroup == mDisplay ||
+ mozilla::StyleDisplay::TableColumn == mDisplay ||
+ mozilla::StyleDisplay::TableColumnGroup == mDisplay;
+ }
+
+ bool IsFloatingStyle() const {
+ return mozilla::StyleFloat::None != mFloat;
+ }
+
+ bool IsAbsolutelyPositionedStyle() const {
+ return NS_STYLE_POSITION_ABSOLUTE == mPosition ||
+ NS_STYLE_POSITION_FIXED == mPosition;
+ }
+
+ bool IsRelativelyPositionedStyle() const {
+ return NS_STYLE_POSITION_RELATIVE == mPosition ||
+ NS_STYLE_POSITION_STICKY == mPosition;
+ }
+ bool IsPositionForcingStackingContext() const {
+ return NS_STYLE_POSITION_STICKY == mPosition ||
+ NS_STYLE_POSITION_FIXED == mPosition;
+ }
+
+ static bool IsRubyDisplayType(mozilla::StyleDisplay aDisplay) {
+ return mozilla::StyleDisplay::Ruby == aDisplay ||
+ mozilla::StyleDisplay::RubyBase == aDisplay ||
+ mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||
+ mozilla::StyleDisplay::RubyText == aDisplay ||
+ mozilla::StyleDisplay::RubyTextContainer == aDisplay;
+ }
+
+ bool IsRubyDisplayType() const {
+ return IsRubyDisplayType(mDisplay);
+ }
+
+ bool IsOutOfFlowStyle() const {
+ return (IsAbsolutelyPositionedStyle() || IsFloatingStyle());
+ }
+
+ bool IsScrollableOverflow() const {
+ // mOverflowX and mOverflowY always match when one of them is
+ // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
+ return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
+ mOverflowX != NS_STYLE_OVERFLOW_CLIP;
+ }
+
+ bool IsContainPaint() const {
+ return NS_STYLE_CONTAIN_PAINT & mContain;
+ }
+
+ /* Returns whether the element has the -moz-transform property
+ * or a related property. */
+ bool HasTransformStyle() const {
+ return mSpecifiedTransform != nullptr ||
+ mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
+ (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
+ }
+
+ bool HasPerspectiveStyle() const {
+ return mChildPerspective.GetUnit() == eStyleUnit_Coord;
+ }
+
+ bool BackfaceIsHidden() const {
+ return mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
+ }
+
+ // These are defined in nsStyleStructInlines.h.
+
+ // The aContextFrame argument on each of these is the frame this
+ // style struct is for. If the frame is for SVG text, the return
+ // value will be massaged to be something that makes sense for
+ // SVG text.
+ inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
+ inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
+ inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
+ inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
+ inline mozilla::StyleDisplay GetDisplay(const nsIFrame* aContextFrame) const;
+ inline bool IsFloating(const nsIFrame* aContextFrame) const;
+ inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
+ inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
+
+ // These methods are defined in nsStyleStructInlines.h.
+
+ /**
+ * Returns whether the element is a containing block for its
+ * absolutely positioned descendants.
+ * aContextFrame is the frame for which this is the nsStyleDisplay.
+ */
+ inline bool IsAbsPosContainingBlock(const nsIFrame* aContextFrame) const;
+
+ /**
+ * The same as IsAbsPosContainingBlock, except skipping the tests that
+ * are based on the frame rather than the style context (thus
+ * potentially returning a false positive).
+ */
+ template<class StyleContextLike>
+ inline bool IsAbsPosContainingBlockForAppropriateFrame(
+ StyleContextLike* aStyleContext) const;
+
+ /**
+ * Returns true when the element has the transform property
+ * or a related property, and supports CSS transforms.
+ * aContextFrame is the frame for which this is the nsStyleDisplay.
+ */
+ inline bool HasTransform(const nsIFrame* aContextFrame) const;
+
+ /**
+ * Returns true when the element is a containing block for its fixed-pos
+ * descendants.
+ * aContextFrame is the frame for which this is the nsStyleDisplay.
+ */
+ inline bool IsFixedPosContainingBlock(const nsIFrame* aContextFrame) const;
+
+ /**
+ * The same as IsFixedPosContainingBlock, except skipping the tests that
+ * are based on the frame rather than the style context (thus
+ * potentially returning a false positive).
+ */
+ template<class StyleContextLike>
+ inline bool IsFixedPosContainingBlockForAppropriateFrame(
+ StyleContextLike* aStyleContext) const;
+
+private:
+ // Helpers for above functions, which do some but not all of the tests
+ // for them (since transform must be tested separately for each).
+ template<class StyleContextLike>
+ inline bool HasAbsPosContainingBlockStyleInternal(
+ StyleContextLike* aStyleContext) const;
+ template<class StyleContextLike>
+ inline bool HasFixedPosContainingBlockStyleInternal(
+ StyleContextLike* aStyleContext) const;
+
+public:
+ // Return the 'float' and 'clear' properties, with inline-{start,end} values
+ // resolved to {left,right} according to the given writing mode. These are
+ // defined in WritingModes.h.
+ inline mozilla::StyleFloat PhysicalFloats(mozilla::WritingMode aWM) const;
+ inline mozilla::StyleClear PhysicalBreakType(mozilla::WritingMode aWM) const;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
+{
+ explicit nsStyleTable(StyleStructContext aContext);
+ nsStyleTable(const nsStyleTable& aOther);
+ ~nsStyleTable();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleTable* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleTable();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleTable, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleTable& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint(0);
+ }
+
+ uint8_t mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
+ int32_t mSpan; // [reset] the number of columns spanned by a colgroup or col
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder
+{
+ explicit nsStyleTableBorder(StyleStructContext aContext);
+ nsStyleTableBorder(const nsStyleTableBorder& aOther);
+ ~nsStyleTableBorder();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleTableBorder* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleTableBorder();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleTableBorder& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ nscoord mBorderSpacingCol;// [inherited]
+ nscoord mBorderSpacingRow;// [inherited]
+ uint8_t mBorderCollapse;// [inherited]
+ uint8_t mCaptionSide; // [inherited]
+ uint8_t mEmptyCells; // [inherited]
+};
+
+enum nsStyleContentType {
+ eStyleContentType_String = 1,
+ eStyleContentType_Image = 10,
+ eStyleContentType_Attr = 20,
+ eStyleContentType_Counter = 30,
+ eStyleContentType_Counters = 31,
+ eStyleContentType_OpenQuote = 40,
+ eStyleContentType_CloseQuote = 41,
+ eStyleContentType_NoOpenQuote = 42,
+ eStyleContentType_NoCloseQuote = 43,
+ eStyleContentType_AltContent = 50,
+ eStyleContentType_Uninitialized
+};
+
+struct nsStyleContentData
+{
+ nsStyleContentType mType;
+ union {
+ char16_t *mString;
+ imgRequestProxy *mImage;
+ nsCSSValue::Array* mCounters;
+ } mContent;
+#ifdef DEBUG
+ bool mImageTracked;
+#endif
+
+ nsStyleContentData()
+ : mType(eStyleContentType_Uninitialized)
+#ifdef DEBUG
+ , mImageTracked(false)
+#endif
+ {
+ MOZ_COUNT_CTOR(nsStyleContentData);
+ mContent.mString = nullptr;
+ }
+ nsStyleContentData(const nsStyleContentData&);
+
+ ~nsStyleContentData();
+ nsStyleContentData& operator=(const nsStyleContentData& aOther);
+ bool operator==(const nsStyleContentData& aOther) const;
+
+ bool operator!=(const nsStyleContentData& aOther) const {
+ return !(*this == aOther);
+ }
+
+ void TrackImage(mozilla::dom::ImageTracker* aImageTracker);
+ void UntrackImage(mozilla::dom::ImageTracker* aImageTracker);
+
+ void SetImage(imgRequestProxy* aRequest)
+ {
+ MOZ_ASSERT(!mImageTracked,
+ "Setting a new image without untracking the old one!");
+ MOZ_ASSERT(mType == eStyleContentType_Image, "Wrong type!");
+ NS_IF_ADDREF(mContent.mImage = aRequest);
+ }
+};
+
+struct nsStyleCounterData
+{
+ nsString mCounter;
+ int32_t mValue;
+
+ bool operator==(const nsStyleCounterData& aOther) const {
+ return mValue == aOther.mValue && mCounter == aOther.mCounter;
+ }
+
+ bool operator!=(const nsStyleCounterData& aOther) const {
+ return !(*this == aOther);
+ }
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
+{
+ explicit nsStyleContent(StyleStructContext aContext);
+ nsStyleContent(const nsStyleContent& aContent);
+ ~nsStyleContent();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleContent* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ nsChangeHint CalcDifference(const nsStyleContent& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ uint32_t ContentCount() const { return mContents.Length(); } // [reset]
+
+ const nsStyleContentData& ContentAt(uint32_t aIndex) const {
+ return mContents[aIndex];
+ }
+
+ nsStyleContentData& ContentAt(uint32_t aIndex) { return mContents[aIndex]; }
+
+ void AllocateContents(uint32_t aCount) {
+ // We need to run the destructors of the elements of mContents, so we
+ // delete and reallocate even if aCount == mContentCount. (If
+ // nsStyleContentData had its members private and managed their
+ // ownership on setting, we wouldn't need this, but that seems
+ // unnecessary at this point.)
+ mContents.Clear();
+ mContents.SetLength(aCount);
+ }
+
+ uint32_t CounterIncrementCount() const { return mIncrements.Length(); } // [reset]
+ const nsStyleCounterData& CounterIncrementAt(uint32_t aIndex) const {
+ return mIncrements[aIndex];
+ }
+
+ void AllocateCounterIncrements(uint32_t aCount) {
+ mIncrements.Clear();
+ mIncrements.SetLength(aCount);
+ }
+
+ void SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
+ mIncrements[aIndex].mCounter = aCounter;
+ mIncrements[aIndex].mValue = aIncrement;
+ }
+
+ uint32_t CounterResetCount() const { return mResets.Length(); } // [reset]
+ const nsStyleCounterData& CounterResetAt(uint32_t aIndex) const {
+ return mResets[aIndex];
+ }
+
+ void AllocateCounterResets(uint32_t aCount) {
+ mResets.Clear();
+ mResets.SetLength(aCount);
+ }
+
+ void SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
+ mResets[aIndex].mCounter = aCounter;
+ mResets[aIndex].mValue = aValue;
+ }
+
+protected:
+ nsTArray<nsStyleContentData> mContents;
+ nsTArray<nsStyleCounterData> mIncrements;
+ nsTArray<nsStyleCounterData> mResets;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset
+{
+ explicit nsStyleUIReset(StyleStructContext aContext);
+ nsStyleUIReset(const nsStyleUIReset& aOther);
+ ~nsStyleUIReset();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleUIReset* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleUIReset();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleUIReset& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ mozilla::StyleUserSelect mUserSelect; // [reset](selection-style)
+ uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
+ uint8_t mIMEMode; // [reset]
+ mozilla::StyleWindowDragging mWindowDragging; // [reset]
+ uint8_t mWindowShadow; // [reset]
+};
+
+struct nsCursorImage
+{
+ bool mHaveHotspot;
+ float mHotspotX, mHotspotY;
+
+ nsCursorImage();
+ nsCursorImage(const nsCursorImage& aOther);
+ ~nsCursorImage();
+
+ nsCursorImage& operator=(const nsCursorImage& aOther);
+
+ bool operator==(const nsCursorImage& aOther) const;
+ bool operator!=(const nsCursorImage& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ void SetImage(imgIRequest *aImage) {
+ if (mImage) {
+ mImage->UnlockImage();
+ mImage->RequestDiscard();
+ }
+ mImage = aImage;
+ if (mImage) {
+ mImage->LockImage();
+ }
+ }
+ imgIRequest* GetImage() const {
+ return mImage;
+ }
+
+private:
+ nsCOMPtr<imgIRequest> mImage;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
+{
+ explicit nsStyleUserInterface(StyleStructContext aContext);
+ nsStyleUserInterface(const nsStyleUserInterface& aOther);
+ ~nsStyleUserInterface();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleUserInterface* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleUserInterface();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleUserInterface& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ nsChangeHint_NeedReflow |
+ nsChangeHint_NeedDirtyReflow |
+ NS_STYLE_HINT_VISUAL |
+ nsChangeHint_UpdateCursor |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow;
+ }
+
+ mozilla::StyleUserInput mUserInput; // [inherited]
+ mozilla::StyleUserModify mUserModify; // [inherited] (modify-content)
+ mozilla::StyleUserFocus mUserFocus; // [inherited] (auto-select)
+ uint8_t mPointerEvents; // [inherited] see nsStyleConsts.h
+
+ uint8_t mCursor; // [inherited] See nsStyleConsts.h
+ nsTArray<nsCursorImage> mCursorImages; // [inherited] images and coords
+
+ inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
+{
+ explicit nsStyleXUL(StyleStructContext aContext);
+ nsStyleXUL(const nsStyleXUL& aSource);
+ ~nsStyleXUL();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleXUL* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleXUL();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleXUL, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleXUL& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ float mBoxFlex; // [reset] see nsStyleConsts.h
+ uint32_t mBoxOrdinal; // [reset] see nsStyleConsts.h
+ mozilla::StyleBoxAlign mBoxAlign; // [reset]
+ mozilla::StyleBoxDirection mBoxDirection; // [reset]
+ mozilla::StyleBoxOrient mBoxOrient; // [reset]
+ mozilla::StyleBoxPack mBoxPack; // [reset]
+ bool mStretchStack; // [reset] see nsStyleConsts.h
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
+{
+ explicit nsStyleColumn(StyleStructContext aContext);
+ nsStyleColumn(const nsStyleColumn& aSource);
+ ~nsStyleColumn();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleColumn* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleColumn();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleColumn, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleColumn& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_ReconstructFrame |
+ NS_STYLE_HINT_REFLOW |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ /**
+ * This is the maximum number of columns we can process. It's used in both
+ * nsColumnSetFrame and nsRuleNode.
+ */
+ static const uint32_t kMaxColumnCount = 1000;
+
+ uint32_t mColumnCount; // [reset] see nsStyleConsts.h
+ nsStyleCoord mColumnWidth; // [reset] coord, auto
+ nsStyleCoord mColumnGap; // [reset] coord, normal
+
+ mozilla::StyleComplexColor mColumnRuleColor; // [reset]
+ uint8_t mColumnRuleStyle; // [reset]
+ uint8_t mColumnFill; // [reset] see nsStyleConsts.h
+
+ void SetColumnRuleWidth(nscoord aWidth) {
+ mColumnRuleWidth = NS_ROUND_BORDER_TO_PIXELS(aWidth, mTwipsPerPixel);
+ }
+
+ nscoord GetComputedColumnRuleWidth() const {
+ return (IsVisibleBorderStyle(mColumnRuleStyle) ? mColumnRuleWidth : 0);
+ }
+
+protected:
+ nscoord mColumnRuleWidth; // [reset] coord
+ nscoord mTwipsPerPixel;
+};
+
+enum nsStyleSVGPaintType {
+ eStyleSVGPaintType_None = 1,
+ eStyleSVGPaintType_Color,
+ eStyleSVGPaintType_Server,
+ eStyleSVGPaintType_ContextFill,
+ eStyleSVGPaintType_ContextStroke
+};
+
+enum nsStyleSVGOpacitySource : uint8_t {
+ eStyleSVGOpacitySource_Normal,
+ eStyleSVGOpacitySource_ContextFillOpacity,
+ eStyleSVGOpacitySource_ContextStrokeOpacity
+};
+
+class nsStyleSVGPaint
+{
+public:
+ explicit nsStyleSVGPaint(nsStyleSVGPaintType aType = nsStyleSVGPaintType(0));
+ nsStyleSVGPaint(const nsStyleSVGPaint& aSource);
+ ~nsStyleSVGPaint();
+
+ nsStyleSVGPaint& operator=(const nsStyleSVGPaint& aOther);
+
+ nsStyleSVGPaintType Type() const { return mType; }
+
+ void SetNone();
+ void SetColor(nscolor aColor);
+ void SetPaintServer(mozilla::css::URLValue* aPaintServer,
+ nscolor aFallbackColor);
+ void SetContextValue(nsStyleSVGPaintType aType,
+ nscolor aFallbackColor);
+
+ nscolor GetColor() const {
+ MOZ_ASSERT(mType == eStyleSVGPaintType_Color);
+ return mPaint.mColor;
+ }
+
+ mozilla::css::URLValue* GetPaintServer() const {
+ MOZ_ASSERT(mType == eStyleSVGPaintType_Server);
+ return mPaint.mPaintServer;
+ }
+
+ nscolor GetFallbackColor() const {
+ MOZ_ASSERT(mType == eStyleSVGPaintType_Server ||
+ mType == eStyleSVGPaintType_ContextFill ||
+ mType == eStyleSVGPaintType_ContextStroke);
+ return mFallbackColor;
+ }
+
+ bool operator==(const nsStyleSVGPaint& aOther) const;
+ bool operator!=(const nsStyleSVGPaint& aOther) const {
+ return !(*this == aOther);
+ }
+
+private:
+ void Reset();
+ void Assign(const nsStyleSVGPaint& aOther);
+
+ union {
+ nscolor mColor;
+ mozilla::css::URLValue* mPaintServer;
+ } mPaint;
+ nsStyleSVGPaintType mType;
+ nscolor mFallbackColor;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
+{
+ explicit nsStyleSVG(StyleStructContext aContext);
+ nsStyleSVG(const nsStyleSVG& aSource);
+ ~nsStyleSVG();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleSVG* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleSVG();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVG, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleSVG& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_UpdateEffects |
+ nsChangeHint_NeedReflow |
+ nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
+ nsChangeHint_RepaintFrame;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns nsChangeHint_NeedReflow as a hint
+ // not handled for descendants, and never returns
+ // nsChangeHint_ClearAncestorIntrinsics at all.
+ return nsChangeHint_NeedReflow;
+ }
+
+ nsStyleSVGPaint mFill; // [inherited]
+ nsStyleSVGPaint mStroke; // [inherited]
+ RefPtr<mozilla::css::URLValue> mMarkerEnd; // [inherited]
+ RefPtr<mozilla::css::URLValue> mMarkerMid; // [inherited]
+ RefPtr<mozilla::css::URLValue> mMarkerStart; // [inherited]
+ nsTArray<nsStyleCoord> mStrokeDasharray; // [inherited] coord, percent, factor
+
+ nsStyleCoord mStrokeDashoffset; // [inherited] coord, percent, factor
+ nsStyleCoord mStrokeWidth; // [inherited] coord, percent, factor
+
+ float mFillOpacity; // [inherited]
+ float mStrokeMiterlimit; // [inherited]
+ float mStrokeOpacity; // [inherited]
+
+ mozilla::StyleFillRule mClipRule; // [inherited]
+ uint8_t mColorInterpolation; // [inherited] see nsStyleConsts.h
+ uint8_t mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
+ mozilla::StyleFillRule mFillRule; // [inherited] see nsStyleConsts.h
+ uint8_t mPaintOrder; // [inherited] see nsStyleConsts.h
+ uint8_t mShapeRendering; // [inherited] see nsStyleConsts.h
+ uint8_t mStrokeLinecap; // [inherited] see nsStyleConsts.h
+ uint8_t mStrokeLinejoin; // [inherited] see nsStyleConsts.h
+ uint8_t mTextAnchor; // [inherited] see nsStyleConsts.h
+
+ nsStyleSVGOpacitySource FillOpacitySource() const {
+ uint8_t value = (mContextFlags & FILL_OPACITY_SOURCE_MASK) >>
+ FILL_OPACITY_SOURCE_SHIFT;
+ return nsStyleSVGOpacitySource(value);
+ }
+ nsStyleSVGOpacitySource StrokeOpacitySource() const {
+ uint8_t value = (mContextFlags & STROKE_OPACITY_SOURCE_MASK) >>
+ STROKE_OPACITY_SOURCE_SHIFT;
+ return nsStyleSVGOpacitySource(value);
+ }
+ bool StrokeDasharrayFromObject() const {
+ return mContextFlags & STROKE_DASHARRAY_CONTEXT;
+ }
+ bool StrokeDashoffsetFromObject() const {
+ return mContextFlags & STROKE_DASHOFFSET_CONTEXT;
+ }
+ bool StrokeWidthFromObject() const {
+ return mContextFlags & STROKE_WIDTH_CONTEXT;
+ }
+
+ void SetFillOpacitySource(nsStyleSVGOpacitySource aValue) {
+ mContextFlags = (mContextFlags & ~FILL_OPACITY_SOURCE_MASK) |
+ (aValue << FILL_OPACITY_SOURCE_SHIFT);
+ }
+ void SetStrokeOpacitySource(nsStyleSVGOpacitySource aValue) {
+ mContextFlags = (mContextFlags & ~STROKE_OPACITY_SOURCE_MASK) |
+ (aValue << STROKE_OPACITY_SOURCE_SHIFT);
+ }
+ void SetStrokeDasharrayFromObject(bool aValue) {
+ mContextFlags = (mContextFlags & ~STROKE_DASHARRAY_CONTEXT) |
+ (aValue ? STROKE_DASHARRAY_CONTEXT : 0);
+ }
+ void SetStrokeDashoffsetFromObject(bool aValue) {
+ mContextFlags = (mContextFlags & ~STROKE_DASHOFFSET_CONTEXT) |
+ (aValue ? STROKE_DASHOFFSET_CONTEXT : 0);
+ }
+ void SetStrokeWidthFromObject(bool aValue) {
+ mContextFlags = (mContextFlags & ~STROKE_WIDTH_CONTEXT) |
+ (aValue ? STROKE_WIDTH_CONTEXT : 0);
+ }
+
+ bool HasMarker() const {
+ return mMarkerStart || mMarkerMid || mMarkerEnd;
+ }
+
+ /**
+ * Returns true if the stroke is not "none" and the stroke-opacity is greater
+ * than zero. This ignores stroke-widths as that depends on the context.
+ */
+ bool HasStroke() const {
+ return mStroke.Type() != eStyleSVGPaintType_None && mStrokeOpacity > 0;
+ }
+
+ /**
+ * Returns true if the fill is not "none" and the fill-opacity is greater
+ * than zero.
+ */
+ bool HasFill() const {
+ return mFill.Type() != eStyleSVGPaintType_None && mFillOpacity > 0;
+ }
+
+private:
+ // Flags to represent the use of context-fill and context-stroke
+ // for fill-opacity or stroke-opacity, and context-value for stroke-dasharray,
+ // stroke-dashoffset and stroke-width.
+ enum {
+ FILL_OPACITY_SOURCE_MASK = 0x03, // fill-opacity: context-{fill,stroke}
+ STROKE_OPACITY_SOURCE_MASK = 0x0C, // stroke-opacity: context-{fill,stroke}
+ STROKE_DASHARRAY_CONTEXT = 0x10, // stroke-dasharray: context-value
+ STROKE_DASHOFFSET_CONTEXT = 0x20, // stroke-dashoffset: context-value
+ STROKE_WIDTH_CONTEXT = 0x40, // stroke-width: context-value
+ FILL_OPACITY_SOURCE_SHIFT = 0,
+ STROKE_OPACITY_SOURCE_SHIFT = 2,
+ };
+
+ uint8_t mContextFlags; // [inherited]
+};
+
+struct nsStyleFilter
+{
+ nsStyleFilter();
+ nsStyleFilter(const nsStyleFilter& aSource);
+ ~nsStyleFilter();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ nsStyleFilter& operator=(const nsStyleFilter& aOther);
+
+ bool operator==(const nsStyleFilter& aOther) const;
+ bool operator!=(const nsStyleFilter& aOther) const {
+ return !(*this == aOther);
+ }
+
+ uint32_t GetType() const {
+ return mType;
+ }
+
+ const nsStyleCoord& GetFilterParameter() const {
+ NS_ASSERTION(mType != NS_STYLE_FILTER_DROP_SHADOW &&
+ mType != NS_STYLE_FILTER_URL &&
+ mType != NS_STYLE_FILTER_NONE, "wrong filter type");
+ return mFilterParameter;
+ }
+ void SetFilterParameter(const nsStyleCoord& aFilterParameter,
+ int32_t aType);
+
+ mozilla::css::URLValue* GetURL() const {
+ MOZ_ASSERT(mType == NS_STYLE_FILTER_URL, "wrong filter type");
+ return mURL;
+ }
+
+ bool SetURL(mozilla::css::URLValue* aValue);
+
+ nsCSSShadowArray* GetDropShadow() const {
+ NS_ASSERTION(mType == NS_STYLE_FILTER_DROP_SHADOW, "wrong filter type");
+ return mDropShadow;
+ }
+ void SetDropShadow(nsCSSShadowArray* aDropShadow);
+
+private:
+ void ReleaseRef();
+
+ uint32_t mType; // see NS_STYLE_FILTER_* constants in nsStyleConsts.h
+ nsStyleCoord mFilterParameter; // coord, percent, factor, angle
+ union {
+ mozilla::css::URLValue* mURL;
+ nsCSSShadowArray* mDropShadow;
+ };
+};
+
+template<>
+struct nsTArray_CopyChooser<nsStyleFilter>
+{
+ typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset
+{
+ explicit nsStyleSVGReset(StyleStructContext aContext);
+ nsStyleSVGReset(const nsStyleSVGReset& aSource);
+ ~nsStyleSVGReset();
+
+ // Resolves and tracks the images in mMask. Only called with a Servo-backed
+ // style system, where those images must be resolved later than the OMT
+ // nsStyleSVGReset constructor call.
+ void FinishStyle(nsPresContext* aPresContext);
+
+ void* operator new(size_t sz, nsStyleSVGReset* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
+ }
+ void Destroy(nsPresContext* aContext);
+
+ nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_UpdateEffects |
+ nsChangeHint_UpdateOverflow |
+ nsChangeHint_NeutralChange |
+ nsChangeHint_RepaintFrame |
+ nsChangeHint_UpdateBackgroundPosition |
+ NS_STYLE_HINT_REFLOW;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ bool HasClipPath() const {
+ return mClipPath.GetType() != mozilla::StyleShapeSourceType::None;
+ }
+
+ bool HasNonScalingStroke() const {
+ return mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE;
+ }
+
+ nsStyleImageLayers mMask;
+ mozilla::StyleClipPath mClipPath; // [reset]
+ nscolor mStopColor; // [reset]
+ nscolor mFloodColor; // [reset]
+ nscolor mLightingColor; // [reset]
+
+ float mStopOpacity; // [reset]
+ float mFloodOpacity; // [reset]
+
+ uint8_t mDominantBaseline; // [reset] see nsStyleConsts.h
+ uint8_t mVectorEffect; // [reset] see nsStyleConsts.h
+ uint8_t mMaskType; // [reset] see nsStyleConsts.h
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables
+{
+ explicit nsStyleVariables(StyleStructContext aContext);
+ nsStyleVariables(const nsStyleVariables& aSource);
+ ~nsStyleVariables();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleVariables* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleVariables();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleVariables, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleVariables& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint(0);
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns nsChangeHint_NeedReflow or
+ // nsChangeHint_ClearAncestorIntrinsics at all.
+ return nsChangeHint(0);
+ }
+
+ mozilla::CSSVariableValues mVariables;
+};
+
+struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects
+{
+ explicit nsStyleEffects(StyleStructContext aContext);
+ nsStyleEffects(const nsStyleEffects& aSource);
+ ~nsStyleEffects();
+ void FinishStyle(nsPresContext* aPresContext) {}
+
+ void* operator new(size_t sz, nsStyleEffects* aSelf) { return aSelf; }
+ void* operator new(size_t sz, nsPresContext* aContext) {
+ return aContext->PresShell()->
+ AllocateByObjectID(mozilla::eArenaObjectID_nsStyleEffects, sz);
+ }
+ void Destroy(nsPresContext* aContext) {
+ this->~nsStyleEffects();
+ aContext->PresShell()->
+ FreeByObjectID(mozilla::eArenaObjectID_nsStyleEffects, this);
+ }
+
+ nsChangeHint CalcDifference(const nsStyleEffects& aNewData) const;
+ static nsChangeHint MaxDifference() {
+ return nsChangeHint_AllReflowHints |
+ nsChangeHint_UpdateOverflow |
+ nsChangeHint_SchedulePaint |
+ nsChangeHint_RepaintFrame |
+ nsChangeHint_UpdateOpacityLayer |
+ nsChangeHint_UpdateUsesOpacity |
+ nsChangeHint_UpdateContainingBlock |
+ nsChangeHint_UpdateEffects |
+ nsChangeHint_NeutralChange;
+ }
+ static nsChangeHint DifferenceAlwaysHandledForDescendants() {
+ // CalcDifference never returns the reflow hints that are sometimes
+ // handled for descendants as hints not handled for descendants.
+ return nsChangeHint_NeedReflow |
+ nsChangeHint_ReflowChangesSizeOrPosition |
+ nsChangeHint_ClearAncestorIntrinsics;
+ }
+
+ bool HasFilters() const {
+ return !mFilters.IsEmpty();
+ }
+
+ nsTArray<nsStyleFilter> mFilters; // [reset]
+ RefPtr<nsCSSShadowArray> mBoxShadow; // [reset] nullptr for 'none'
+ nsRect mClip; // [reset] offsets from UL border edge
+ float mOpacity; // [reset]
+ uint8_t mClipFlags; // [reset] see nsStyleConsts.h
+ uint8_t mMixBlendMode; // [reset] see nsStyleConsts.h
+};
+
+#define STATIC_ASSERT_TYPE_LAYOUTS_MATCH(T1, T2) \
+ static_assert(sizeof(T1) == sizeof(T2), \
+ "Size mismatch between " #T1 " and " #T2); \
+ static_assert(alignof(T1) == alignof(T2), \
+ "Align mismatch between " #T1 " and " #T2); \
+
+#define STATIC_ASSERT_FIELD_OFFSET_MATCHES(T1, T2, field) \
+ static_assert(offsetof(T1, field) == offsetof(T2, field), \
+ "Field offset mismatch of " #field " between " #T1 " and " #T2); \
+
+/**
+ * These *_Simple types are used to map Gecko types to layout-equivalent but
+ * simpler Rust types, to aid Rust binding generation.
+ *
+ * If something in this types or the assertions below needs to change, ask
+ * bholley, heycam or emilio before!
+ *
+ * <div rustbindgen="true" replaces="nsPoint">
+ */
+struct nsPoint_Simple {
+ nscoord x, y;
+};
+
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsPoint, nsPoint_Simple);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsPoint, nsPoint_Simple, x);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsPoint, nsPoint_Simple, y);
+
+/**
+ * <div rustbindgen="true" replaces="nsMargin">
+ */
+struct nsMargin_Simple {
+ nscoord top, right, bottom, left;
+};
+
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsMargin, nsMargin_Simple);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, top);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, right);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, bottom);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, left);
+
+/**
+ * <div rustbindgen="true" replaces="nsRect">
+ */
+struct nsRect_Simple {
+ nscoord x, y, width, height;
+};
+
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsRect, nsRect_Simple);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, x);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, y);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, width);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, height);
+
+/**
+ * <div rustbindgen="true" replaces="nsSize">
+ */
+struct nsSize_Simple {
+ nscoord width, height;
+};
+
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsSize, nsSize_Simple);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsSize, nsSize_Simple, width);
+STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsSize, nsSize_Simple, height);
+
+/**
+ * <div rustbindgen="true" replaces="UniquePtr">
+ *
+ * TODO(Emilio): This is a workaround and we should be able to get rid of this
+ * one.
+ */
+template<typename T, typename Deleter = mozilla::DefaultDelete<T>>
+struct UniquePtr_Simple {
+ T* mPtr;
+};
+
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(mozilla::UniquePtr<int>, UniquePtr_Simple<int>);
+
+/**
+ * <div rustbindgen replaces="nsTArray"></div>
+ */
+template<typename T>
+class nsTArray_Simple {
+ T* mBuffer;
+public:
+ // The existence of a destructor here prevents bindgen from deriving the Clone
+ // trait via a simple memory copy.
+ ~nsTArray_Simple() {};
+};
+
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<nsStyleImageLayers::Layer>,
+ nsTArray_Simple<nsStyleImageLayers::Layer>);
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleTransition>,
+ nsTArray_Simple<mozilla::StyleTransition>);
+STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleAnimation>,
+ nsTArray_Simple<mozilla::StyleAnimation>);
+
+#endif /* nsStyleStruct_h___ */