diff options
Diffstat (limited to 'layout/style/nsComputedDOMStyle.h')
-rw-r--r-- | layout/style/nsComputedDOMStyle.h | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h new file mode 100644 index 0000000000..f1ac3cc221 --- /dev/null +++ b/layout/style/nsComputedDOMStyle.h @@ -0,0 +1,395 @@ +/* -*- 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 <typename T> + using Span = mozilla::Span<T>; + 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<const ComputedStyle> GetComputedStyle( + Element* aElement, PseudoStyleType = PseudoStyleType::NotPseudo, + StyleType = StyleType::All); + + static already_AddRefed<const ComputedStyle> GetComputedStyleNoFlush( + const Element* aElement, + PseudoStyleType aPseudo = PseudoStyleType::NotPseudo, + StyleType aStyleType = StyleType::All) { + return DoGetComputedStyleNoFlush( + aElement, aPseudo, nsContentUtils::GetPresShellForContent(aElement), + aStyleType); + } + + static already_AddRefed<const ComputedStyle> + 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<nsCString>& 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<nsROCSSPrimitiveValue> 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<const ComputedStyle>&& aContext, + uint64_t aGeneration); + void SetFrameComputedStyle(ComputedStyle* aStyle, uint64_t aGeneration); + + static already_AddRefed<const ComputedStyle> 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<CSSValue> GetOffsetWidthFor(mozilla::Side); + already_AddRefed<CSSValue> GetAbsoluteOffset(mozilla::Side); + nscoord GetUsedAbsoluteOffset(mozilla::Side); + already_AddRefed<CSSValue> GetNonStaticPositionOffset( + mozilla::Side aSide, bool aResolveAuto, PercentageBaseGetter aWidthGetter, + PercentageBaseGetter aHeightGetter); + + already_AddRefed<CSSValue> GetStaticOffset(mozilla::Side aSide); + + already_AddRefed<CSSValue> GetPaddingWidthFor(mozilla::Side aSide); + + already_AddRefed<CSSValue> GetBorderWidthFor(mozilla::Side aSide); + + already_AddRefed<CSSValue> GetMarginFor(mozilla::Side aSide); + + already_AddRefed<CSSValue> GetTransformValue(const mozilla::StyleTransform&); + + already_AddRefed<nsROCSSPrimitiveValue> GetGridTrackSize( + const mozilla::StyleTrackSize&); + already_AddRefed<nsROCSSPrimitiveValue> GetGridTrackBreadth( + const mozilla::StyleTrackBreadth&); + void SetValueToTrackBreadth(nsROCSSPrimitiveValue*, + const mozilla::StyleTrackBreadth&); + already_AddRefed<CSSValue> 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<CSSValue> DoGetWidth(); + already_AddRefed<CSSValue> DoGetHeight(); + already_AddRefed<CSSValue> DoGetMaxHeight(); + already_AddRefed<CSSValue> DoGetMaxWidth(); + already_AddRefed<CSSValue> DoGetMinHeight(); + already_AddRefed<CSSValue> DoGetMinWidth(); + already_AddRefed<CSSValue> DoGetLeft(); + already_AddRefed<CSSValue> DoGetTop(); + already_AddRefed<CSSValue> DoGetRight(); + already_AddRefed<CSSValue> DoGetBottom(); + + /* Font properties */ + already_AddRefed<CSSValue> DoGetMozOsxFontSmoothing(); + + /* Grid properties */ + already_AddRefed<CSSValue> DoGetGridTemplateColumns(); + already_AddRefed<CSSValue> DoGetGridTemplateRows(); + + /* StyleImageLayer properties */ + already_AddRefed<CSSValue> DoGetImageLayerPosition( + const nsStyleImageLayers& aLayers); + + /* Padding properties */ + already_AddRefed<CSSValue> DoGetPaddingTop(); + already_AddRefed<CSSValue> DoGetPaddingBottom(); + already_AddRefed<CSSValue> DoGetPaddingLeft(); + already_AddRefed<CSSValue> DoGetPaddingRight(); + + /* Table Properties */ + already_AddRefed<CSSValue> DoGetBorderSpacing(); + + /* Border Properties */ + already_AddRefed<CSSValue> DoGetBorderTopWidth(); + already_AddRefed<CSSValue> DoGetBorderBottomWidth(); + already_AddRefed<CSSValue> DoGetBorderLeftWidth(); + already_AddRefed<CSSValue> DoGetBorderRightWidth(); + + /* Margin Properties */ + already_AddRefed<CSSValue> DoGetMarginTop(); + already_AddRefed<CSSValue> DoGetMarginBottom(); + already_AddRefed<CSSValue> DoGetMarginLeft(); + already_AddRefed<CSSValue> DoGetMarginRight(); + + /* Display properties */ + already_AddRefed<CSSValue> DoGetTransform(); + already_AddRefed<CSSValue> DoGetTransformOrigin(); + already_AddRefed<CSSValue> DoGetPerspectiveOrigin(); + + // For working around a MSVC bug. See related comment in + // GenerateComputedDOMStyleGenerated.py. + already_AddRefed<CSSValue> 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<Element> 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<const ComputedStyle> 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<nsComputedDOMStyle> NS_NewComputedDOMStyle( + mozilla::dom::Element*, const nsAString& aPseudoElt, + mozilla::dom::Document*, nsComputedDOMStyle::StyleType, + mozilla::ErrorResult&); + +#endif /* nsComputedDOMStyle_h__ */ |