nsComputedDOMStyle.h (15239B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* DOM object returned from element.getComputedStyle() */ 8 9 #ifndef nsComputedDOMStyle_h__ 10 #define nsComputedDOMStyle_h__ 11 12 #include "mozilla/ComputedStyle.h" 13 #include "mozilla/PseudoStyleType.h" 14 #include "mozilla/StyleColorInlines.h" 15 #include "mozilla/WritingModes.h" 16 #include "mozilla/gfx/Types.h" 17 #include "nsCOMPtr.h" 18 #include "nsColor.h" 19 #include "nsContentUtils.h" 20 #include "nsCoord.h" 21 #include "nsDOMCSSDeclaration.h" 22 #include "nsIWeakReferenceUtils.h" 23 #include "nsStubMutationObserver.h" 24 #include "nsStyleStruct.h" 25 #include "nsStyleStructList.h" 26 #include "nscore.h" 27 28 // XXX Avoid including this here by moving function bodies to the cpp file 29 #include "mozilla/dom/Element.h" 30 31 namespace mozilla { 32 enum class FlushType : uint8_t; 33 34 namespace dom { 35 class DocGroup; 36 class Element; 37 } // namespace dom 38 class PresShell; 39 struct ComputedGridTrackInfo; 40 } // namespace mozilla 41 42 struct ComputedStyleMap; 43 struct nsCSSKTableEntry; 44 class nsIFrame; 45 class nsDOMCSSValueList; 46 struct nsMargin; 47 class nsROCSSPrimitiveValue; 48 class nsStyleGradient; 49 50 class nsComputedDOMStyle final : public nsDOMCSSDeclaration, 51 public nsStubMutationObserver { 52 private: 53 // Convenience typedefs: 54 template <typename T> 55 using Span = mozilla::Span<T>; 56 using KTableEntry = nsCSSKTableEntry; 57 using CSSValue = mozilla::dom::CSSValue; 58 using StyleGeometryBox = mozilla::StyleGeometryBox; 59 using Element = mozilla::dom::Element; 60 using Document = mozilla::dom::Document; 61 using PseudoStyleRequest = mozilla::PseudoStyleRequest; 62 using LengthPercentage = mozilla::LengthPercentage; 63 using LengthPercentageOrAuto = mozilla::LengthPercentageOrAuto; 64 using ComputedStyle = mozilla::ComputedStyle; 65 66 public: 67 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 68 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_AMBIGUOUS( 69 nsComputedDOMStyle, nsICSSDeclaration) 70 71 NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER 72 73 void GetPropertyValue(const NonCustomCSSPropertyId aPropId, 74 nsACString& aValue) override; 75 void SetPropertyValue(const NonCustomCSSPropertyId aPropId, 76 const nsACString& aValue, 77 nsIPrincipal* aSubjectPrincipal, 78 mozilla::ErrorResult& aRv) override; 79 80 void IndexedGetter(uint32_t aIndex, bool& aFound, 81 nsACString& aPropName) final; 82 83 enum class StyleType : uint8_t { 84 DefaultOnly, // Only includes UA and user sheets 85 All // Includes all stylesheets 86 }; 87 88 // In some cases, for legacy reasons, we forcefully return an empty style. 89 enum class AlwaysReturnEmptyStyle : bool { No, Yes }; 90 91 nsComputedDOMStyle(Element*, PseudoStyleRequest&&, Document*, StyleType, 92 AlwaysReturnEmptyStyle = AlwaysReturnEmptyStyle::No); 93 94 nsINode* GetAssociatedNode() const override { return mElement; } 95 nsINode* GetParentObject() const override { return mElement; } 96 97 static already_AddRefed<const ComputedStyle> GetComputedStyle( 98 Element* aElement, const PseudoStyleRequest& aType = {}, 99 StyleType = StyleType::All); 100 101 static already_AddRefed<const ComputedStyle> GetComputedStyleNoFlush( 102 const Element* aElement, const PseudoStyleRequest& aPseudo = {}, 103 StyleType aStyleType = StyleType::All) { 104 return DoGetComputedStyleNoFlush( 105 aElement, aPseudo, nsContentUtils::GetPresShellForContent(aElement), 106 aStyleType); 107 } 108 109 static already_AddRefed<const ComputedStyle> 110 GetUnanimatedComputedStyleNoFlush(Element*, const PseudoStyleRequest&); 111 112 // Helper for nsDOMWindowUtils::GetVisitedDependentComputedStyle 113 void SetExposeVisitedStyle(bool aExpose) { 114 NS_ASSERTION(aExpose != mExposeVisitedStyle, "should always be changing"); 115 mExposeVisitedStyle = aExpose; 116 } 117 118 float UsedFontSize() final; 119 120 void GetCSSImageURLs(const nsACString& aPropertyName, 121 nsTArray<nsCString>& aImageURLs, 122 mozilla::ErrorResult& aRv) final; 123 124 // nsDOMCSSDeclaration abstract methods which should never be called 125 // on a nsComputedDOMStyle object, but must be defined to avoid 126 // compile errors. 127 mozilla::DeclarationBlock* GetOrCreateCSSDeclaration( 128 Operation aOperation, mozilla::DeclarationBlock** aCreated) final; 129 virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock*, 130 mozilla::MutationClosureData*) override; 131 virtual mozilla::dom::Document* DocToUpdate() final; 132 133 nsDOMCSSDeclaration::ParsingEnvironment GetParsingEnvironment( 134 nsIPrincipal* aSubjectPrincipal) const final; 135 136 static already_AddRefed<nsROCSSPrimitiveValue> MatrixToCSSValue( 137 const mozilla::gfx::Matrix4x4& aMatrix); 138 139 static void RegisterPrefChangeCallbacks(); 140 static void UnregisterPrefChangeCallbacks(); 141 142 // nsIMutationObserver 143 NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED 144 145 private: 146 already_AddRefed<nsROCSSPrimitiveValue> AppUnitsToCSSValue(nscoord); 147 already_AddRefed<nsROCSSPrimitiveValue> PixelsToCSSValue(float); 148 void SetValueToPixels(nsROCSSPrimitiveValue*, float); 149 150 void GetPropertyValue(const NonCustomCSSPropertyId aPropId, 151 const nsACString& aMaybeCustomPropertyNme, 152 nsACString& aValue); 153 using nsDOMCSSDeclaration::GetPropertyValue; 154 155 virtual ~nsComputedDOMStyle(); 156 157 void AssertFlushedPendingReflows() { 158 NS_ASSERTION(mFlushedPendingReflows, 159 "property getter should have been marked layout-dependent"); 160 } 161 162 nsMargin GetAdjustedValuesForBoxSizing(); 163 164 // This indicates error by leaving mComputedStyle null. 165 void UpdateCurrentStyleSources(NonCustomCSSPropertyId); 166 void ClearCurrentStyleSources(); 167 168 // Helper functions called by UpdateCurrentStyleSources. 169 void ClearComputedStyle(); 170 void SetResolvedComputedStyle(RefPtr<const ComputedStyle>, 171 uint64_t aGeneration); 172 void SetFrameComputedStyle(RefPtr<const ComputedStyle>, uint64_t aGeneration); 173 174 static already_AddRefed<const ComputedStyle> DoGetComputedStyleNoFlush( 175 const Element*, const PseudoStyleRequest&, mozilla::PresShell*, 176 StyleType); 177 178 #define COMPUTED_STYLE_ACCESSOR(name_) \ 179 const nsStyle##name_* Style##name_() const { \ 180 return mComputedStyle->Style##name_(); \ 181 } 182 FOR_EACH_STYLE_STRUCT(COMPUTED_STYLE_ACCESSOR, COMPUTED_STYLE_ACCESSOR) 183 #undef COMPUTED_STYLE_ACCESSOR 184 185 /** 186 * A method to get a percentage base for a percentage value. Returns true 187 * if a percentage base value was determined, false otherwise. 188 */ 189 typedef bool (nsComputedDOMStyle::*PercentageBaseGetter)(nscoord&); 190 191 already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side); 192 already_AddRefed<CSSValue> GetAbsoluteOffset(mozilla::Side); 193 nscoord GetUsedAbsoluteOffset(mozilla::Side); 194 already_AddRefed<CSSValue> GetNonStaticPositionOffset( 195 mozilla::Side aSide, bool aResolveAuto, PercentageBaseGetter aWidthGetter, 196 PercentageBaseGetter aHeightGetter); 197 198 already_AddRefed<CSSValue> GetStaticOffset(mozilla::Side aSide); 199 200 already_AddRefed<CSSValue> GetPaddingWidthFor(mozilla::Side aSide); 201 202 already_AddRefed<CSSValue> GetMarginFor(mozilla::Side aSide); 203 204 already_AddRefed<CSSValue> GetTransformValue(const mozilla::StyleTransform&); 205 206 already_AddRefed<nsROCSSPrimitiveValue> GetGridTrackSize( 207 const mozilla::StyleTrackSize&); 208 already_AddRefed<nsROCSSPrimitiveValue> GetGridTrackBreadth( 209 const mozilla::StyleTrackBreadth&); 210 void SetValueToTrackBreadth(nsROCSSPrimitiveValue*, 211 const mozilla::StyleTrackBreadth&); 212 already_AddRefed<CSSValue> GetGridTemplateColumnsRows( 213 const mozilla::StyleGridTemplateComponent& aTrackList, 214 const mozilla::ComputedGridTrackInfo& aTrackInfo); 215 216 bool GetLineHeightCoord(nscoord& aCoord); 217 218 bool ShouldHonorMinSizeAutoInAxis(mozilla::PhysicalAxis aAxis); 219 220 /* Properties queryable as CSSValues. 221 * To avoid a name conflict with nsIDOM*CSS2Properties, these are all 222 * DoGetXXX instead of GetXXX. 223 */ 224 225 /* Box properties */ 226 227 already_AddRefed<CSSValue> DoGetWidth(); 228 already_AddRefed<CSSValue> DoGetHeight(); 229 already_AddRefed<CSSValue> DoGetMaxHeight(); 230 already_AddRefed<CSSValue> DoGetMaxWidth(); 231 already_AddRefed<CSSValue> DoGetMinHeight(); 232 already_AddRefed<CSSValue> DoGetMinWidth(); 233 already_AddRefed<CSSValue> DoGetLeft(); 234 already_AddRefed<CSSValue> DoGetTop(); 235 already_AddRefed<CSSValue> DoGetRight(); 236 already_AddRefed<CSSValue> DoGetBottom(); 237 238 /* Font properties */ 239 already_AddRefed<CSSValue> DoGetMozOsxFontSmoothing(); 240 241 /* Grid properties */ 242 already_AddRefed<CSSValue> DoGetGridTemplateColumns(); 243 already_AddRefed<CSSValue> DoGetGridTemplateRows(); 244 245 /* StyleImageLayer properties */ 246 already_AddRefed<CSSValue> DoGetImageLayerPosition( 247 const nsStyleImageLayers& aLayers); 248 249 /* Padding properties */ 250 already_AddRefed<CSSValue> DoGetPaddingTop(); 251 already_AddRefed<CSSValue> DoGetPaddingBottom(); 252 already_AddRefed<CSSValue> DoGetPaddingLeft(); 253 already_AddRefed<CSSValue> DoGetPaddingRight(); 254 255 /* Margin Properties */ 256 already_AddRefed<CSSValue> DoGetMarginTop(); 257 already_AddRefed<CSSValue> DoGetMarginBottom(); 258 already_AddRefed<CSSValue> DoGetMarginLeft(); 259 already_AddRefed<CSSValue> DoGetMarginRight(); 260 261 /* Display properties */ 262 already_AddRefed<CSSValue> DoGetTransform(); 263 already_AddRefed<CSSValue> DoGetTransformOrigin(); 264 already_AddRefed<CSSValue> DoGetPerspectiveOrigin(); 265 266 // For working around a MSVC bug. See related comment in 267 // GenerateComputedDOMStyleGenerated.py. 268 already_AddRefed<CSSValue> DummyGetter(); 269 270 /* Helper functions */ 271 void SetValueToPosition(const mozilla::Position& aPosition, 272 nsDOMCSSValueList* aValueList); 273 274 void SetValueFromFitContentFunction(nsROCSSPrimitiveValue* aValue, 275 const mozilla::LengthPercentage&); 276 277 void SetValueToSize(nsROCSSPrimitiveValue* aValue, const AnchorResolvedSize&); 278 279 void SetValueToLengthPercentageOrAuto(nsROCSSPrimitiveValue* aValue, 280 const LengthPercentageOrAuto&, 281 bool aClampNegativeCalc); 282 void SetValueToMargin(nsROCSSPrimitiveValue* aValue, 283 const mozilla::StyleMargin&); 284 285 void SetValueToLengthPercentage(nsROCSSPrimitiveValue* aValue, 286 const LengthPercentage&, 287 bool aClampNegativeCalc); 288 289 void SetValueToMaxSize(nsROCSSPrimitiveValue* aValue, 290 const AnchorResolvedMaxSize&); 291 292 bool GetCBContentWidth(nscoord& aWidth); 293 bool GetCBContentHeight(nscoord& aHeight); 294 bool GetCBPaddingRectWidth(nscoord& aWidth); 295 bool GetCBPaddingRectHeight(nscoord& aHeight); 296 bool GetScrollFrameContentWidth(nscoord& aWidth); 297 bool GetScrollFrameContentHeight(nscoord& aHeight); 298 bool GetFrameBorderRectWidth(nscoord& aWidth); 299 bool GetFrameBorderRectHeight(nscoord& aHeight); 300 301 // Find out if we can safely skip flushing (i.e. pending restyles do not 302 // affect our element). 303 bool NeedsToFlushStyle(NonCustomCSSPropertyId) const; 304 // Find out if we need to flush layout of the document, depending on the 305 // property that was requested. 306 bool NeedsToFlushLayout(NonCustomCSSPropertyId) const; 307 // Find out if we need to flush layout of the document due to container 308 // query being made before relevant query containers are reflowed at least 309 // once. 310 bool NeedsToFlushLayoutForContainerQuery() const; 311 // Flushes the given document, which must be our document, and potentially the 312 // mElement's document. 313 void Flush(Document&, mozilla::FlushType); 314 nsIFrame* GetOuterFrame() const; 315 316 static ComputedStyleMap* GetComputedStyleMap(); 317 318 // We don't really have a good immutable representation of "presentation". 319 // Given the way GetComputedStyle is currently used, we should just grab the 320 // presshell, if any, from the document. 321 mozilla::WeakPtr<mozilla::dom::Document> mDocumentWeak; 322 RefPtr<Element> mElement; 323 324 /** 325 * Strong reference to the ComputedStyle we access data from. This can be 326 * either a ComputedStyle we resolved ourselves or a ComputedStyle we got 327 * from our frame. 328 * 329 * If we got the ComputedStyle from the frame, we clear out mComputedStyle 330 * in ClearCurrentStyleSources. If we resolved one ourselves, then 331 * ClearCurrentStyleSources leaves it in mComputedStyle for use the next 332 * time this nsComputedDOMStyle object is queried. UpdateCurrentStyleSources 333 * in this case will check that the ComputedStyle is still valid to be used, 334 * by checking whether flush styles results in any restyles having been 335 * processed. 336 */ 337 RefPtr<const ComputedStyle> mComputedStyle; 338 339 /* 340 * While computing style data, the primary frame for mContent --- named 341 * "outer" because we should use it to compute positioning data. Null 342 * otherwise. 343 */ 344 nsIFrame* mOuterFrame; 345 /* 346 * While computing style data, the "inner frame" for mContent --- the frame 347 * which we should use to compute margin, border, padding and content data. 348 * Null otherwise. 349 */ 350 nsIFrame* mInnerFrame; 351 /* 352 * While computing style data, the presshell we're working with. Null 353 * otherwise. 354 */ 355 mozilla::PresShell* mPresShell; 356 357 /* 358 * The pseudo style request which packs PseudoStyleType and the function 359 * parameter if any. 360 */ 361 PseudoStyleRequest mPseudo; 362 363 /* The kind of styles we should be returning. */ 364 StyleType mStyleType; 365 366 /* Whether for legacy reasons we return an empty style (when an unknown 367 * pseudo-element is specified) */ 368 AlwaysReturnEmptyStyle mAlwaysReturnEmpty; 369 370 /** 371 * The nsComputedDOMStyle generation at the time we last resolved a style 372 * context and stored it in mComputedStyle, and the pres shell we got the 373 * style from. Should only be used together. 374 */ 375 uint64_t mComputedStyleGeneration = 0; 376 377 uint32_t mPresShellId = 0; 378 379 bool mExposeVisitedStyle = false; 380 381 /** 382 * Whether we resolved a ComputedStyle last time we called 383 * UpdateCurrentStyleSources. Initially false. 384 */ 385 bool mResolvedComputedStyle = false; 386 387 #ifdef DEBUG 388 bool mFlushedPendingReflows = false; 389 #endif 390 391 friend struct ComputedStyleMap; 392 friend AnchorPosResolutionParams AnchorPosResolutionParams::From( 393 const nsComputedDOMStyle*); 394 }; 395 396 already_AddRefed<nsComputedDOMStyle> NS_NewComputedDOMStyle( 397 mozilla::dom::Element*, const nsAString& aPseudoElt, 398 mozilla::dom::Document*, nsComputedDOMStyle::StyleType, 399 mozilla::ErrorResult&); 400 401 inline AnchorPosResolutionParams AnchorPosResolutionParams::From( 402 const nsComputedDOMStyle* aComputedDOMStyle) { 403 AutoResolutionOverrideParams overrides{aComputedDOMStyle->mOuterFrame}; 404 return {aComputedDOMStyle->mOuterFrame, 405 aComputedDOMStyle->StyleDisplay()->mPosition, nullptr, overrides}; 406 } 407 408 #endif /* nsComputedDOMStyle_h__ */