/* -*- 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/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; class nsComputedDOMStyle final : public nsDOMCSSDeclaration, public nsStubMutationObserver { private: // Convenience typedefs: using KTableEntry = nsCSSKTableEntry; using CSSValue = mozilla::dom::CSSValue; using StyleGeometryBox = mozilla::StyleGeometryBox; using Element = mozilla::dom::Element; using Document = mozilla::dom::Document; using StyleFlexBasis = mozilla::StyleFlexBasis; using StyleSize = mozilla::StyleSize; using StyleMaxSize = mozilla::StyleMaxSize; using LengthPercentage = mozilla::LengthPercentage; using LengthPercentageOrAuto = mozilla::LengthPercentageOrAuto; using StyleExtremumLength = mozilla::StyleExtremumLength; using ComputedStyle = mozilla::ComputedStyle; 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(Element* aElement, const nsAString& aPseudoElt, Document* aDocument, StyleType aStyleType); nsINode* GetParentObject() override { return mElement; } static already_AddRefed GetComputedStyle( Element* aElement, nsAtom* aPseudo, StyleType aStyleType = eAll); static already_AddRefed GetComputedStyleNoFlush( Element* aElement, nsAtom* aPseudo, StyleType aStyleType = eAll) { return DoGetComputedStyleNoFlush( aElement, aPseudo, nsContentUtils::GetPresShellForContent(aElement), aStyleType); } static already_AddRefed GetUnanimatedComputedStyleNoFlush( 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 mozilla::dom::Document* DocToUpdate() override; nsDOMCSSDeclaration::ParsingEnvironment GetParsingEnvironment( nsIPrincipal* aSubjectPrincipal) const final; static already_AddRefed MatrixToCSSValue( const mozilla::gfx::Matrix4x4& aMatrix); static void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor); 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(); // 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(ComputedStyle* aStyle, uint64_t aGeneration); static already_AddRefed DoGetComputedStyleNoFlush( 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 /** * 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&); already_AddRefed GetEllipseRadii(const nsStyleCorners& aRadius, mozilla::Corner aFullCorner); already_AddRefed GetOffsetWidthFor(mozilla::Side aSide); already_AddRefed GetAbsoluteOffset(mozilla::Side); nscoord GetUsedAbsoluteOffset(mozilla::Side); already_AddRefed GetNonStaticPositionOffset( mozilla::Side aSide, bool aResolveAuto, PercentageBaseGetter aWidthGetter, PercentageBaseGetter aHeightGetter); 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); 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 DoGetLeft(); already_AddRefed DoGetTop(); already_AddRefed DoGetRight(); already_AddRefed DoGetBottom(); /* Color */ already_AddRefed DoGetColor(); /* Font properties */ already_AddRefed DoGetOsxFontSmoothing(); /* 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 DoGetImageLayerPosition( const nsStyleImageLayers& aLayers); /* Mask properties */ already_AddRefed DoGetMask(); /* 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 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 DoGetBorderImageSlice(); already_AddRefed DoGetBorderImageWidth(); already_AddRefed DoGetBorderImageOutset(); /* Box Shadow */ already_AddRefed DoGetBoxShadow(); /* Margin Properties */ already_AddRefed DoGetMarginTopWidth(); already_AddRefed DoGetMarginBottomWidth(); already_AddRefed DoGetMarginLeftWidth(); already_AddRefed DoGetMarginRightWidth(); /* Outline Properties */ already_AddRefed DoGetOutlineWidth(); already_AddRefed DoGetOutlineRadiusBottomLeft(); already_AddRefed DoGetOutlineRadiusBottomRight(); already_AddRefed DoGetOutlineRadiusTopLeft(); already_AddRefed DoGetOutlineRadiusTopRight(); /* z-index */ already_AddRefed DoGetZIndex(); /* Text Properties */ already_AddRefed DoGetInitialLetter(); already_AddRefed DoGetLineHeight(); 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(); /* Display properties */ already_AddRefed DoGetBinding(); already_AddRefed DoGetDisplay(); already_AddRefed DoGetContain(); already_AddRefed DoGetWillChange(); already_AddRefed DoGetTouchAction(); already_AddRefed DoGetTransform(); already_AddRefed DoGetTransformOrigin(); already_AddRefed DoGetPerspective(); already_AddRefed DoGetPerspectiveOrigin(); already_AddRefed DoGetScrollSnapPointsX(); already_AddRefed DoGetScrollSnapPointsY(); already_AddRefed DoGetScrollbarColor(); /* User interface properties */ already_AddRefed DoGetCaretColor(); 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(); /* CSS Animations */ already_AddRefed DoGetAnimationName(); already_AddRefed DoGetAnimationDuration(); already_AddRefed DoGetAnimationDelay(); already_AddRefed DoGetAnimationIterationCount(); /* CSS Flexbox properties */ already_AddRefed DoGetFlexBasis(); already_AddRefed DoGetFlexGrow(); already_AddRefed DoGetFlexShrink(); /* CSS Box Alignment properties */ 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 DoGetFilter(); already_AddRefed DoGetPaintOrder(); // For working around a MSVC bug. See related comment in // GenerateComputedDOMStyleGenerated.py. already_AddRefed DummyGetter(); /* Helper functions */ void SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue, const mozilla::StyleComplexColor& aColor); void SetValueToPosition(const mozilla::Position& aPosition, nsDOMCSSValueList* aValueList); void SetValueToURLValue(const mozilla::css::URLValue* aURL, nsROCSSPrimitiveValue* aValue); void SetValueToSize(nsROCSSPrimitiveValue* aValue, const mozilla::StyleSize&, nscoord aMinAppUnits = nscoord_MIN, nscoord aMaxAppUnits = nscoord_MAX); void SetValueToLengthPercentageOrAuto(nsROCSSPrimitiveValue* aValue, const LengthPercentageOrAuto&, bool aClampNegativeCalc); void SetValueToLengthPercentage(nsROCSSPrimitiveValue* aValue, const LengthPercentage&, bool aClampNegativeCalc, nscoord aMinAppUnits = nscoord_MIN, nscoord aMaxAppUnits = nscoord_MAX); void SetValueToMaxSize(nsROCSSPrimitiveValue* aValue, const StyleMaxSize&); void SetValueToExtremumLength(nsROCSSPrimitiveValue* aValue, StyleExtremumLength); /** * 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 percentage base can't * be determined, returns aDefaultValue. */ nscoord StyleCoordToNSCoord(const LengthPercentage& aCoord, PercentageBaseGetter aPercentageBaseGetter, nscoord aDefaultValue, bool aClampNegativeCalc); template nscoord StyleCoordToNSCoord(const LengthPercentageLike& aCoord, PercentageBaseGetter aPercentageBaseGetter, nscoord aDefaultValue, bool aClampNegativeCalc) { if (aCoord.IsLengthPercentage()) { return StyleCoordToNSCoord(aCoord.AsLengthPercentage(), aPercentageBaseGetter, aDefaultValue, aClampNegativeCalc); } return aDefaultValue; } /** * 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& aHeight); bool GetCBPaddingRectWidth(nscoord& aWidth); bool GetCBPaddingRectHeight(nscoord& aHeight); 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); 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(Document*) 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. */ RefPtr 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, and the pres shell we got the * style from. Should only be used together. */ uint64_t mComputedStyleGeneration = 0; uint32_t mPresShellId = 0; 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, mozilla::dom::Document* aDocument, nsComputedDOMStyle::StyleType aStyleType = nsComputedDOMStyle::eAll); #endif /* nsComputedDOMStyle_h__ */