/* -*- 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/StyleColorInlines.h" #include "mozilla/UniquePtr.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 "nsStubMutationObserver.h" #include "nsStyleStruct.h" #include "mozilla/WritingModes.h" // XXX Avoid including this here by moving function bodies to the cpp file #include "mozilla/dom/Element.h" namespace mozilla { enum class FlushType : uint8_t; enum class PseudoStyleType : uint8_t; namespace dom { class DocGroup; class Element; } // namespace dom class PresShell; struct ComputedGridTrackInfo; } // namespace mozilla struct ComputedStyleMap; struct nsCSSKTableEntry; class nsIFrame; class nsDOMCSSValueList; struct nsMargin; class nsROCSSPrimitiveValue; class nsStyleGradient; class nsComputedDOMStyle final : public nsDOMCSSDeclaration, public nsStubMutationObserver { private: // Convenience typedefs: template using Span = mozilla::Span; using KTableEntry = nsCSSKTableEntry; using CSSValue = mozilla::dom::CSSValue; using StyleGeometryBox = mozilla::StyleGeometryBox; using Element = mozilla::dom::Element; using Document = mozilla::dom::Document; using PseudoStyleType = mozilla::PseudoStyleType; using LengthPercentage = mozilla::LengthPercentage; using LengthPercentageOrAuto = mozilla::LengthPercentageOrAuto; using ComputedStyle = mozilla::ComputedStyle; public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_AMBIGUOUS( nsComputedDOMStyle, nsICSSDeclaration) NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER nsresult GetPropertyValue(const nsCSSPropertyID aPropID, nsACString& aValue) override; void SetPropertyValue(const nsCSSPropertyID aPropID, const nsACString& aValue, nsIPrincipal* aSubjectPrincipal, mozilla::ErrorResult& aRv) override; void IndexedGetter(uint32_t aIndex, bool& aFound, nsACString& aPropName) final; enum class StyleType : uint8_t { DefaultOnly, // Only includes UA and user sheets All // Includes all stylesheets }; // In some cases, for legacy reasons, we forcefully return an empty style. enum class AlwaysReturnEmptyStyle : bool { No, Yes }; nsComputedDOMStyle(Element*, PseudoStyleType, Document*, StyleType, AlwaysReturnEmptyStyle = AlwaysReturnEmptyStyle::No); nsINode* GetAssociatedNode() const override { return mElement; } nsINode* GetParentObject() const override { return mElement; } static already_AddRefed GetComputedStyle( Element* aElement, PseudoStyleType = PseudoStyleType::NotPseudo, StyleType = StyleType::All); static already_AddRefed GetComputedStyleNoFlush( const Element* aElement, PseudoStyleType aPseudo = PseudoStyleType::NotPseudo, StyleType aStyleType = StyleType::All) { return DoGetComputedStyleNoFlush( aElement, aPseudo, nsContentUtils::GetPresShellForContent(aElement), aStyleType); } static already_AddRefed GetUnanimatedComputedStyleNoFlush( Element*, PseudoStyleType = PseudoStyleType::NotPseudo); // Helper for nsDOMWindowUtils::GetVisitedDependentComputedStyle void SetExposeVisitedStyle(bool aExpose) { NS_ASSERTION(aExpose != mExposeVisitedStyle, "should always be changing"); mExposeVisitedStyle = aExpose; } void GetCSSImageURLs(const nsACString& 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 RegisterPrefChangeCallbacks(); static void UnregisterPrefChangeCallbacks(); // nsIMutationObserver NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED private: nsresult GetPropertyValue(const nsCSSPropertyID aPropID, const nsACString& aMaybeCustomPropertyNme, nsACString& aValue); 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(nsCSSPropertyID); 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( const Element*, PseudoStyleType, mozilla::PresShell*, StyleType); #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 GetOffsetWidthFor(mozilla::Side); 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 GetBorderWidthFor(mozilla::Side aSide); already_AddRefed GetMarginFor(mozilla::Side aSide); already_AddRefed GetTransformValue(const mozilla::StyleTransform&); already_AddRefed GetGridTrackSize( const mozilla::StyleTrackSize&); already_AddRefed GetGridTrackBreadth( const mozilla::StyleTrackBreadth&); void SetValueToTrackBreadth(nsROCSSPrimitiveValue*, const mozilla::StyleTrackBreadth&); already_AddRefed GetGridTemplateColumnsRows( const mozilla::StyleGridTemplateComponent& aTrackList, const mozilla::ComputedGridTrackInfo& aTrackInfo); bool GetLineHeightCoord(nscoord& 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 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(); /* Font properties */ already_AddRefed DoGetMozOsxFontSmoothing(); /* Grid properties */ already_AddRefed DoGetGridTemplateColumns(); already_AddRefed DoGetGridTemplateRows(); /* StyleImageLayer properties */ already_AddRefed DoGetImageLayerPosition( const nsStyleImageLayers& aLayers); /* Padding properties */ already_AddRefed DoGetPaddingTop(); already_AddRefed DoGetPaddingBottom(); already_AddRefed DoGetPaddingLeft(); already_AddRefed DoGetPaddingRight(); /* Table Properties */ already_AddRefed DoGetBorderSpacing(); /* Border Properties */ already_AddRefed DoGetBorderTopWidth(); already_AddRefed DoGetBorderBottomWidth(); already_AddRefed DoGetBorderLeftWidth(); already_AddRefed DoGetBorderRightWidth(); /* Margin Properties */ already_AddRefed DoGetMarginTop(); already_AddRefed DoGetMarginBottom(); already_AddRefed DoGetMarginLeft(); already_AddRefed DoGetMarginRight(); /* Text Properties */ already_AddRefed DoGetLineHeight(); /* Display properties */ already_AddRefed DoGetTransform(); already_AddRefed DoGetTransformOrigin(); already_AddRefed DoGetPerspectiveOrigin(); // For working around a MSVC bug. See related comment in // GenerateComputedDOMStyleGenerated.py. already_AddRefed DummyGetter(); /* Helper functions */ void SetValueToPosition(const mozilla::Position& aPosition, nsDOMCSSValueList* aValueList); void SetValueToURLValue(const mozilla::StyleComputedUrl* aURL, nsROCSSPrimitiveValue* aValue); void SetValueFromFitContentFunction(nsROCSSPrimitiveValue* aValue, const mozilla::LengthPercentage&); void SetValueToSize(nsROCSSPrimitiveValue* aValue, const mozilla::StyleSize&); void SetValueToLengthPercentageOrAuto(nsROCSSPrimitiveValue* aValue, const LengthPercentageOrAuto&, bool aClampNegativeCalc); void SetValueToLengthPercentage(nsROCSSPrimitiveValue* aValue, const LengthPercentage&, bool aClampNegativeCalc); void SetValueToMaxSize(nsROCSSPrimitiveValue* aValue, const mozilla::StyleMaxSize&); 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 GetFrameBorderRectWidth(nscoord& aWidth); bool GetFrameBorderRectHeight(nscoord& aHeight); // Find out if we can safely skip flushing (i.e. pending restyles do not // affect our element). bool NeedsToFlushStyle(nsCSSPropertyID) const; // Find out if we need to flush layout of the document, depending on the // property that was requested. bool NeedsToFlushLayout(nsCSSPropertyID) const; // Flushes the given document, which must be our document, and potentially the // mElement's document. void Flush(Document&, mozilla::FlushType); nsIFrame* GetOuterFrame() 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; /* * 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. */ mozilla::PresShell* mPresShell; PseudoStyleType mPseudo; /* The kind of styles we should be returning. */ StyleType mStyleType; /* Whether for legacy reasons we return an empty style (when an unknown * pseudo-element is specified) */ AlwaysReturnEmptyStyle mAlwaysReturnEmpty; /** * 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 = false; /** * Whether we resolved a ComputedStyle last time we called * UpdateCurrentStyleSources. Initially false. */ bool mResolvedComputedStyle = false; #ifdef DEBUG bool mFlushedPendingReflows = false; #endif friend struct ComputedStyleMap; }; already_AddRefed NS_NewComputedDOMStyle( mozilla::dom::Element*, const nsAString& aPseudoElt, mozilla::dom::Document*, nsComputedDOMStyle::StyleType, mozilla::ErrorResult&); #endif /* nsComputedDOMStyle_h__ */