/* -*- 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/. */ /* DOM object returned from element.getComputedStyle() */ #ifndef nsComputedDOMStyle_h__ #define nsComputedDOMStyle_h__ #include "mozilla/ArenaRefPtr.h" #include "mozilla/ArenaRefPtrInlines.h" #include "mozilla/Attributes.h" #include "mozilla/StyleComplexColor.h" #include "mozilla/UniquePtr.h" #include "mozilla/dom/Element.h" #include "nsCOMPtr.h" #include "nsContentUtils.h" #include "nscore.h" #include "nsDOMCSSDeclaration.h" #include "mozilla/ComputedStyle.h" #include "nsIWeakReferenceUtils.h" #include "mozilla/gfx/Types.h" #include "nsCoord.h" #include "nsColor.h" #include "nsStyleStruct.h" #include "mozilla/WritingModes.h" namespace mozilla { namespace dom { class DocGroup; class Element; } // namespace dom struct ComputedGridTrackInfo; } // namespace mozilla struct ComputedStyleMap; struct nsCSSKTableEntry; class nsIFrame; class nsIPresShell; class nsDOMCSSValueList; struct nsMargin; class nsROCSSPrimitiveValue; class nsStyleCoord; class nsStyleCorners; struct nsStyleFilter; class nsStyleGradient; struct nsStyleImage; class nsStyleSides; struct nsTimingFunction; class nsComputedDOMStyle final : public nsDOMCSSDeclaration , public nsStubMutationObserver { private: // Convenience typedefs: typedef nsCSSKTableEntry KTableEntry; typedef mozilla::dom::CSSValue CSSValue; typedef mozilla::StyleGeometryBox StyleGeometryBox; public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsComputedDOMStyle, nsICSSDeclaration) NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER nsresult GetPropertyValue(const nsCSSPropertyID aPropID, nsAString& aValue) override; nsresult SetPropertyValue(const nsCSSPropertyID aPropID, const nsAString& aValue, nsIPrincipal* aSubjectPrincipal) override; void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aPropName) final; enum StyleType { eDefaultOnly, // Only includes UA and user sheets eAll // Includes all stylesheets }; nsComputedDOMStyle(mozilla::dom::Element* aElement, const nsAString& aPseudoElt, nsIDocument* aDocument, StyleType aStyleType); nsINode* GetParentObject() override { return mElement; } static already_AddRefed GetComputedStyle(mozilla::dom::Element* aElement, nsAtom* aPseudo, StyleType aStyleType = eAll); static already_AddRefed GetComputedStyleNoFlush(mozilla::dom::Element* aElement, nsAtom* aPseudo, StyleType aStyleType = eAll) { return DoGetComputedStyleNoFlush(aElement, aPseudo, nsContentUtils::GetPresShellForContent(aElement), aStyleType); } static already_AddRefed GetUnanimatedComputedStyleNoFlush(mozilla::dom::Element* aElement, nsAtom* aPseudo); // Helper for nsDOMWindowUtils::GetVisitedDependentComputedStyle void SetExposeVisitedStyle(bool aExpose) { NS_ASSERTION(aExpose != mExposeVisitedStyle, "should always be changing"); mExposeVisitedStyle = aExpose; } void GetCSSImageURLs(const nsAString& aPropertyName, nsTArray& aImageURLs, mozilla::ErrorResult& aRv) final; // nsDOMCSSDeclaration abstract methods which should never be called // on a nsComputedDOMStyle object, but must be defined to avoid // compile errors. mozilla::DeclarationBlock* GetOrCreateCSSDeclaration( Operation aOperation, mozilla::DeclarationBlock** aCreated) final; virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock*, mozilla::MutationClosureData*) override; virtual nsIDocument* DocToUpdate() override; nsDOMCSSDeclaration::ParsingEnvironment GetParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final; static already_AddRefed MatrixToCSSValue(const mozilla::gfx::Matrix4x4& aMatrix); static void RegisterPrefChangeCallbacks(); static void UnregisterPrefChangeCallbacks(); // nsIMutationObserver NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED private: virtual ~nsComputedDOMStyle(); void AssertFlushedPendingReflows() { NS_ASSERTION(mFlushedPendingReflows, "property getter should have been marked layout-dependent"); } nsMargin GetAdjustedValuesForBoxSizing(); // Helper method for DoGetTextAlign[Last]. already_AddRefed CreateTextAlignValue(uint8_t aAlign, bool aAlignTrue, const KTableEntry aTable[]); // This indicates error by leaving mComputedStyle null. void UpdateCurrentStyleSources(bool aNeedsLayoutFlush); void ClearCurrentStyleSources(); // Helper functions called by UpdateCurrentStyleSources. void ClearComputedStyle(); void SetResolvedComputedStyle(RefPtr&& aContext, uint64_t aGeneration); void SetFrameComputedStyle(mozilla::ComputedStyle* aStyle, uint64_t aGeneration); static already_AddRefed DoGetComputedStyleNoFlush(mozilla::dom::Element* aElement, nsAtom* aPseudo, nsIPresShell* aPresShell, StyleType aStyleType); #define STYLE_STRUCT(name_) \ const nsStyle##name_ * Style##name_() { \ return mComputedStyle->Style##name_(); \ } #include "nsStyleStructList.h" #undef STYLE_STRUCT already_AddRefed GetEllipseRadii(const nsStyleCorners& aRadius, mozilla::Corner aFullCorner); already_AddRefed GetOffsetWidthFor(mozilla::Side aSide); already_AddRefed GetAbsoluteOffset(mozilla::Side aSide); already_AddRefed GetRelativeOffset(mozilla::Side aSide); already_AddRefed GetStickyOffset(mozilla::Side aSide); already_AddRefed GetStaticOffset(mozilla::Side aSide); already_AddRefed GetPaddingWidthFor(mozilla::Side aSide); already_AddRefed GetBorderStyleFor(mozilla::Side aSide); already_AddRefed GetBorderWidthFor(mozilla::Side aSide); already_AddRefed GetBorderColorFor(mozilla::Side aSide); already_AddRefed GetMarginWidthFor(mozilla::Side aSide); already_AddRefed GetFallbackValue(const nsStyleSVGPaint* aPaint); already_AddRefed GetSVGPaintFor(bool aFill); already_AddRefed GetTransformValue(nsCSSValueSharedList* aSpecifiedTransform); // Appends all aLineNames (may be empty) space-separated to aResult. void AppendGridLineNames(nsString& aResult, const nsTArray& aLineNames); // Appends aLineNames as a CSSValue* to aValueList. If aLineNames is empty // a value ("[]") is only appended if aSuppressEmptyList is false. void AppendGridLineNames(nsDOMCSSValueList* aValueList, const nsTArray& aLineNames, bool aSuppressEmptyList = true); // Appends aLineNames1/2 (if non-empty) as a CSSValue* to aValueList. void AppendGridLineNames(nsDOMCSSValueList* aValueList, const nsTArray& aLineNames1, const nsTArray& aLineNames2); already_AddRefed GetGridTrackSize(const nsStyleCoord& aMinSize, const nsStyleCoord& aMaxSize); already_AddRefed GetGridTemplateColumnsRows( const nsStyleGridTemplate& aTrackList, const mozilla::ComputedGridTrackInfo* aTrackInfo); already_AddRefed GetGridLine(const nsStyleGridLine& aGridLine); bool GetLineHeightCoord(nscoord& aCoord); already_AddRefed GetCSSShadowArray(nsCSSShadowArray* aArray, bool aIsBoxShadow); void GetCSSGradientString(const nsStyleGradient* aGradient, nsAString& aString); void GetImageRectString(nsIURI* aURI, const nsStyleSides& aCropRect, nsString& aString); already_AddRefed GetScrollSnapPoints(const nsStyleCoord& aCoord); void AppendTimingFunction(nsDOMCSSValueList *aValueList, const nsTimingFunction& aTimingFunction); bool ShouldHonorMinSizeAutoInAxis(mozilla::PhysicalAxis aAxis); /* Properties queryable as CSSValues. * To avoid a name conflict with nsIDOM*CSS2Properties, these are all * DoGetXXX instead of GetXXX. */ /* Box properties */ already_AddRefed DoGetBoxFlex(); already_AddRefed DoGetWidth(); already_AddRefed DoGetHeight(); already_AddRefed DoGetMaxHeight(); already_AddRefed DoGetMaxWidth(); already_AddRefed DoGetMinHeight(); already_AddRefed DoGetMinWidth(); already_AddRefed DoGetObjectPosition(); already_AddRefed DoGetLeft(); already_AddRefed DoGetTop(); already_AddRefed DoGetRight(); already_AddRefed DoGetBottom(); /* Color */ already_AddRefed DoGetColor(); /* Font properties */ already_AddRefed DoGetOsxFontSmoothing(); already_AddRefed DoGetFontVariant(); /* Grid properties */ already_AddRefed DoGetGridAutoFlow(); already_AddRefed DoGetGridAutoColumns(); already_AddRefed DoGetGridAutoRows(); already_AddRefed DoGetGridTemplateAreas(); already_AddRefed DoGetGridTemplateColumns(); already_AddRefed DoGetGridTemplateRows(); already_AddRefed DoGetGridColumnStart(); already_AddRefed DoGetGridColumnEnd(); already_AddRefed DoGetGridRowStart(); already_AddRefed DoGetGridRowEnd(); /* StyleImageLayer properties */ already_AddRefed DoGetImageLayerImage(const nsStyleImageLayers& aLayers); already_AddRefed DoGetImageLayerPosition(const nsStyleImageLayers& aLayers); already_AddRefed DoGetImageLayerPositionX(const nsStyleImageLayers& aLayers); already_AddRefed DoGetImageLayerPositionY(const nsStyleImageLayers& aLayers); already_AddRefed DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers); already_AddRefed DoGetImageLayerSize(const nsStyleImageLayers& aLayers); /* Background properties */ already_AddRefed DoGetBackgroundImage(); already_AddRefed DoGetBackgroundPosition(); already_AddRefed DoGetBackgroundPositionX(); already_AddRefed DoGetBackgroundPositionY(); already_AddRefed DoGetBackgroundRepeat(); already_AddRefed DoGetBackgroundSize(); /* Mask properties */ already_AddRefed DoGetMask(); already_AddRefed DoGetMaskImage(); already_AddRefed DoGetMaskPosition(); already_AddRefed DoGetMaskPositionX(); already_AddRefed DoGetMaskPositionY(); already_AddRefed DoGetMaskRepeat(); already_AddRefed DoGetMaskSize(); /* Padding properties */ already_AddRefed DoGetPaddingTop(); already_AddRefed DoGetPaddingBottom(); already_AddRefed DoGetPaddingLeft(); already_AddRefed DoGetPaddingRight(); /* Table Properties */ already_AddRefed DoGetBorderSpacing(); already_AddRefed DoGetVerticalAlign(); /* Border Properties */ already_AddRefed DoGetBorderTopStyle(); already_AddRefed DoGetBorderBottomStyle(); already_AddRefed DoGetBorderLeftStyle(); already_AddRefed DoGetBorderRightStyle(); already_AddRefed DoGetBorderTopWidth(); already_AddRefed DoGetBorderBottomWidth(); already_AddRefed DoGetBorderLeftWidth(); already_AddRefed DoGetBorderRightWidth(); already_AddRefed DoGetBorderBottomLeftRadius(); already_AddRefed DoGetBorderBottomRightRadius(); already_AddRefed DoGetBorderTopLeftRadius(); already_AddRefed DoGetBorderTopRightRadius(); /* Border Image */ already_AddRefed DoGetBorderImageSource(); already_AddRefed DoGetBorderImageSlice(); already_AddRefed DoGetBorderImageWidth(); already_AddRefed DoGetBorderImageOutset(); already_AddRefed DoGetBorderImageRepeat(); /* Box Shadow */ already_AddRefed DoGetBoxShadow(); /* Window Shadow */ /* Margin Properties */ already_AddRefed DoGetMarginTopWidth(); already_AddRefed DoGetMarginBottomWidth(); already_AddRefed DoGetMarginLeftWidth(); already_AddRefed DoGetMarginRightWidth(); /* Outline Properties */ already_AddRefed DoGetOutlineWidth(); already_AddRefed DoGetOutlineStyle(); already_AddRefed DoGetOutlineRadiusBottomLeft(); already_AddRefed DoGetOutlineRadiusBottomRight(); already_AddRefed DoGetOutlineRadiusTopLeft(); already_AddRefed DoGetOutlineRadiusTopRight(); /* Quotes Properties */ already_AddRefed DoGetQuotes(); /* z-index */ already_AddRefed DoGetZIndex(); /* List properties */ already_AddRefed DoGetImageRegion(); /* Text Properties */ already_AddRefed DoGetInitialLetter(); already_AddRefed DoGetLineHeight(); already_AddRefed DoGetTextAlign(); already_AddRefed DoGetTextDecoration(); already_AddRefed DoGetTextDecorationColor(); already_AddRefed DoGetTextDecorationLine(); already_AddRefed DoGetTextDecorationStyle(); already_AddRefed DoGetTextEmphasisPosition(); already_AddRefed DoGetTextEmphasisStyle(); already_AddRefed DoGetTextOverflow(); already_AddRefed DoGetTextShadow(); already_AddRefed DoGetLetterSpacing(); already_AddRefed DoGetWordSpacing(); already_AddRefed DoGetTabSize(); already_AddRefed DoGetWebkitTextStrokeWidth(); /* Visibility properties */ /* Direction properties */ /* Display properties */ already_AddRefed DoGetBinding(); already_AddRefed DoGetDisplay(); already_AddRefed DoGetContain(); already_AddRefed DoGetClip(); already_AddRefed DoGetImageOrientation(); already_AddRefed DoGetWillChange(); already_AddRefed DoGetOverflow(); already_AddRefed DoGetOverflowY(); already_AddRefed DoGetOverflowClipBoxBlock(); already_AddRefed DoGetOverflowClipBoxInline(); already_AddRefed DoGetTouchAction(); already_AddRefed DoGetTransform(); already_AddRefed DoGetTranslate(); already_AddRefed DoGetRotate(); already_AddRefed DoGetScale(); already_AddRefed DoGetTransformOrigin(); already_AddRefed DoGetPerspective(); already_AddRefed DoGetPerspectiveOrigin(); already_AddRefed DoGetTransformStyle(); already_AddRefed DoGetOverscrollBehaviorX(); already_AddRefed DoGetOverscrollBehaviorY(); already_AddRefed DoGetScrollSnapTypeX(); already_AddRefed DoGetScrollSnapTypeY(); already_AddRefed DoGetScrollSnapPointsX(); already_AddRefed DoGetScrollSnapPointsY(); already_AddRefed DoGetScrollSnapDestination(); already_AddRefed DoGetScrollSnapCoordinate(); already_AddRefed DoGetScrollbarFaceColor(); already_AddRefed DoGetScrollbarTrackColor(); already_AddRefed DoGetShapeOutside(); /* User interface properties */ already_AddRefed DoGetCaretColor(); already_AddRefed DoGetCursor(); already_AddRefed DoGetForceBrokenImageIcon(); /* Column properties */ already_AddRefed DoGetColumnCount(); already_AddRefed DoGetColumnWidth(); already_AddRefed DoGetColumnRuleWidth(); /* CSS Transitions */ already_AddRefed DoGetTransitionProperty(); already_AddRefed DoGetTransitionDuration(); already_AddRefed DoGetTransitionDelay(); already_AddRefed DoGetTransitionTimingFunction(); /* CSS Animations */ already_AddRefed DoGetAnimationName(); already_AddRefed DoGetAnimationDuration(); already_AddRefed DoGetAnimationDelay(); already_AddRefed DoGetAnimationTimingFunction(); already_AddRefed DoGetAnimationIterationCount(); /* CSS Flexbox properties */ already_AddRefed DoGetFlexBasis(); already_AddRefed DoGetFlexGrow(); already_AddRefed DoGetFlexShrink(); /* CSS Flexbox/Grid properties */ /* CSS Box Alignment properties */ already_AddRefed DoGetAlignContent(); already_AddRefed DoGetAlignItems(); already_AddRefed DoGetAlignSelf(); already_AddRefed DoGetJustifyContent(); already_AddRefed DoGetJustifyItems(); already_AddRefed DoGetJustifySelf(); already_AddRefed DoGetColumnGap(); already_AddRefed DoGetRowGap(); /* SVG properties */ already_AddRefed DoGetFill(); already_AddRefed DoGetStroke(); already_AddRefed DoGetMarkerEnd(); already_AddRefed DoGetMarkerMid(); already_AddRefed DoGetMarkerStart(); already_AddRefed DoGetStrokeDasharray(); already_AddRefed DoGetStrokeDashoffset(); already_AddRefed DoGetStrokeWidth(); already_AddRefed DoGetFillOpacity(); already_AddRefed DoGetStrokeMiterlimit(); already_AddRefed DoGetStrokeOpacity(); already_AddRefed DoGetClipPath(); already_AddRefed DoGetFilter(); already_AddRefed DoGetPaintOrder(); // For working around a MSVC bug. See related comment in // GenerateComputedDOMStyleGenerated.py. already_AddRefed DummyGetter(); /* Helper functions */ void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor); void SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue, const mozilla::StyleComplexColor& aColor); void SetValueForWidgetColor(nsROCSSPrimitiveValue* aValue, const mozilla::StyleComplexColor& aColor, uint8_t aWidgetType); void SetValueToStyleImage(const nsStyleImage& aStyleImage, nsROCSSPrimitiveValue* aValue); void SetValueToPositionCoord(const mozilla::Position::Coord& aCoord, nsROCSSPrimitiveValue* aValue); void SetValueToPosition(const mozilla::Position& aPosition, nsDOMCSSValueList* aValueList); void SetValueToURLValue(const mozilla::css::URLValueData* aURL, nsROCSSPrimitiveValue* aValue); /** * A method to get a percentage base for a percentage value. Returns true * if a percentage base value was determined, false otherwise. */ typedef bool (nsComputedDOMStyle::*PercentageBaseGetter)(nscoord&); /** * Method to set aValue to aCoord. If aCoord is a percentage value and * aPercentageBaseGetter is not null, aPercentageBaseGetter is called. If it * returns true, the percentage base it outputs in its out param is used * to compute an nscoord value. If the getter is null or returns false, * the percent value of aCoord is set as a percent value on aValue. aTable, * if not null, is the keyword table to handle eStyleUnit_Enumerated. When * calling SetAppUnits on aValue (for coord or percent values), the value * passed in will be clamped to be no less than aMinAppUnits and no more than * aMaxAppUnits. * * XXXbz should caller pass in some sort of bitfield indicating which units * can be expected or something? */ void SetValueToCoord(nsROCSSPrimitiveValue* aValue, const nsStyleCoord& aCoord, bool aClampNegativeCalc, PercentageBaseGetter aPercentageBaseGetter = nullptr, const KTableEntry aTable[] = nullptr, nscoord aMinAppUnits = nscoord_MIN, nscoord aMaxAppUnits = nscoord_MAX); /** * If aCoord is a eStyleUnit_Coord returns the nscoord. If it's * eStyleUnit_Percent, attempts to resolve the percentage base and returns * the resulting nscoord. If it's some other unit or a percentge base can't * be determined, returns aDefaultValue. */ nscoord StyleCoordToNSCoord(const nsStyleCoord& aCoord, PercentageBaseGetter aPercentageBaseGetter, nscoord aDefaultValue, bool aClampNegativeCalc); /** * Append coord values from four sides. It omits values when possible. */ void AppendFourSideCoordValues(nsDOMCSSValueList* aList, const nsStyleSides& aValues); bool GetCBContentWidth(nscoord& aWidth); bool GetCBContentHeight(nscoord& aWidth); bool GetScrollFrameContentWidth(nscoord& aWidth); bool GetScrollFrameContentHeight(nscoord& aHeight); bool GetFrameBoundsWidthForTransform(nscoord &aWidth); bool GetFrameBoundsHeightForTransform(nscoord &aHeight); bool GetFrameBorderRectWidth(nscoord& aWidth); bool GetFrameBorderRectHeight(nscoord& aHeight); /* Helper functions for computing and serializing a nsStyleCoord. */ void SetCssTextToCoord(nsAString& aCssText, const nsStyleCoord& aCoord, bool aClampNegativeCalc); already_AddRefed CreatePrimitiveValueForStyleFilter( const nsStyleFilter& aStyleFilter); already_AddRefed GetShapeSource(const mozilla::StyleShapeSource& aShapeSource, const KTableEntry aBoxKeywordTable[]); template already_AddRefed CreatePrimitiveValueForShapeSource( const mozilla::UniquePtr& aStyleBasicShape, ReferenceBox aReferenceBox, const KTableEntry aBoxKeywordTable[]); // Helper function for computing basic shape styles. already_AddRefed CreatePrimitiveValueForBasicShape( const mozilla::UniquePtr& aStyleBasicShape); void BoxValuesToString(nsAString& aString, const nsTArray& aBoxValues, bool aClampNegativeCalc); void BasicShapeRadiiToString(nsAString& aCssText, const nsStyleCorners& aCorners); // Find out if we can safely skip flushing for aDocument (i.e. pending // restyles does not affect mContent). bool NeedsToFlush(nsIDocument* aDocument) const; static ComputedStyleMap* GetComputedStyleMap(); // We don't really have a good immutable representation of "presentation". // Given the way GetComputedStyle is currently used, we should just grab the // presshell, if any, from the document. nsWeakPtr mDocumentWeak; RefPtr mElement; /** * Strong reference to the ComputedStyle we access data from. This can be * either a ComputedStyle we resolved ourselves or a ComputedStyle we got * from our frame. * * If we got the ComputedStyle from the frame, we clear out mComputedStyle * in ClearCurrentStyleSources. If we resolved one ourselves, then * ClearCurrentStyleSources leaves it in mComputedStyle for use the next * time this nsComputedDOMStyle object is queried. UpdateCurrentStyleSources * in this case will check that the ComputedStyle is still valid to be used, * by checking whether flush styles results in any restyles having been * processed. * * Since an ArenaRefPtr is used to hold the ComputedStyle, it will be cleared * if the pres arena from which it was allocated goes away. */ mozilla::ArenaRefPtr mComputedStyle; RefPtr mPseudo; /* * While computing style data, the primary frame for mContent --- named "outer" * because we should use it to compute positioning data. Null * otherwise. */ nsIFrame* mOuterFrame; /* * While computing style data, the "inner frame" for mContent --- the frame * which we should use to compute margin, border, padding and content data. Null * otherwise. */ nsIFrame* mInnerFrame; /* * While computing style data, the presshell we're working with. Null * otherwise. */ nsIPresShell* mPresShell; /* * The kind of styles we should be returning. */ StyleType mStyleType; /** * The nsComputedDOMStyle generation at the time we last resolved a style * context and stored it in mComputedStyle. */ uint64_t mComputedStyleGeneration; bool mExposeVisitedStyle; /** * Whether we resolved a ComputedStyle last time we called * UpdateCurrentStyleSources. Initially false. */ bool mResolvedComputedStyle; #ifdef DEBUG bool mFlushedPendingReflows; #endif friend struct ComputedStyleMap; }; already_AddRefed NS_NewComputedDOMStyle(mozilla::dom::Element* aElement, const nsAString& aPseudoElt, nsIDocument* aDocument, nsComputedDOMStyle::StyleType aStyleType = nsComputedDOMStyle::eAll); #endif /* nsComputedDOMStyle_h__ */