Bug 1635702 [wpt PR 23413] - Move some internal scroll anchoring tests to wpt, a...
[gecko.git] / layout / style / ComputedStyle.h
blob32cefa75fdb9ed78ca1141d1ff1afa2543028837
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/. */
7 /* the interface (to internal code) for retrieving computed style data */
9 #ifndef _ComputedStyle_h_
10 #define _ComputedStyle_h_
12 #include <algorithm>
13 #include "mozilla/Assertions.h"
14 #include "mozilla/CachedInheritingStyles.h"
15 #include "mozilla/Maybe.h"
16 #include "mozilla/PseudoStyleType.h"
17 #include "mozilla/ServoComputedData.h"
18 #include "mozilla/ServoComputedDataInlines.h"
19 #include "mozilla/ServoStyleConsts.h"
20 #include "mozilla/ServoTypes.h"
21 #include "mozilla/ServoUtils.h"
22 #include "nsCSSAnonBoxes.h"
23 #include "nsCSSPseudoElements.h"
24 #include "nsColor.h"
26 #include "nsStyleStructFwd.h"
28 enum nsChangeHint : uint32_t;
29 class nsPresContext;
30 class nsWindowSizes;
32 #define STYLE_STRUCT(name_) struct nsStyle##name_;
33 #include "nsStyleStructList.h"
34 #undef STYLE_STRUCT
36 extern "C" {
37 void Gecko_ComputedStyle_Destroy(mozilla::ComputedStyle*);
40 namespace mozilla {
42 namespace dom {
43 class Document;
46 class ComputedStyle;
48 /**
49 * A ComputedStyle represents the computed style data for an element.
51 * The computed style data are stored in a set of reference counted structs
52 * (see nsStyleStruct.h) that are stored directly on the ComputedStyle.
54 * Style structs are immutable once they have been produced, so when any change
55 * is made that needs a restyle, we create a new ComputedStyle.
57 * ComputedStyles are reference counted. References are generally held by:
59 * 1. nsIFrame::mComputedStyle, for every frame
60 * 2. Element::mServoData, for every element not inside a display:none subtree
61 * 3. nsComputedDOMStyle, when created for elements in display:none subtrees
62 * 4. media_queries::Device, which holds the initial value of every property
65 class ComputedStyle {
66 using Flag = StyleComputedValueFlags;
68 const StyleComputedValueFlags& Flags() const { return mSource.flags; }
70 public:
71 ComputedStyle(PseudoStyleType aPseudoType,
72 ServoComputedDataForgotten aComputedValues);
74 // Returns the computed (not resolved) value of the given property.
75 void GetComputedPropertyValue(nsCSSPropertyID aId, nsAString& aOut) const {
76 Servo_GetPropertyValue(this, aId, &aOut);
79 // Return the ComputedStyle whose style data should be used for the R,
80 // G, and B components of color, background-color, and border-*-color
81 // if RelevantLinkIsVisited().
83 // GetPseudo() and GetPseudoType() on this ComputedStyle return the
84 // same as on |this|, and its depth in the tree (number of GetParent()
85 // calls until null is returned) is the same as |this|, since its
86 // parent is either |this|'s parent or |this|'s parent's
87 // style-if-visited.
89 // Structs on this context should never be examined without also
90 // examining the corresponding struct on |this|. Doing so will likely
91 // both (1) lead to a privacy leak and (2) lead to dynamic change bugs
92 // related to the Peek code in ComputedStyle::CalcStyleDifference.
93 ComputedStyle* GetStyleIfVisited() const {
94 return mSource.visited_style.mPtr;
97 bool IsLazilyCascadedPseudoElement() const {
98 return IsPseudoElement() &&
99 !nsCSSPseudoElements::IsEagerlyCascadedInServo(GetPseudoType());
102 PseudoStyleType GetPseudoType() const { return mPseudoType; }
104 bool IsPseudoElement() const {
105 return PseudoStyle::IsPseudoElement(mPseudoType);
108 bool IsInheritingAnonBox() const {
109 return PseudoStyle::IsInheritingAnonBox(mPseudoType);
112 bool IsNonInheritingAnonBox() const {
113 return PseudoStyle::IsNonInheritingAnonBox(mPseudoType);
116 bool IsWrapperAnonBox() const {
117 return PseudoStyle::IsWrapperAnonBox(mPseudoType);
120 bool IsAnonBox() const { return PseudoStyle::IsAnonBox(mPseudoType); }
122 bool IsPseudoOrAnonBox() const {
123 return mPseudoType != PseudoStyleType::NotPseudo;
126 // Whether there are author-specified rules for padding properties.
127 // Only returns something meaningful if the appearance property is not `none`.
128 bool HasAuthorSpecifiedPadding() const {
129 return bool(Flags() & Flag::HAS_AUTHOR_SPECIFIED_PADDING);
132 // Whether there are author-specified rules for border or background
133 // properties.
134 // Only returns something meaningful if the appearance property is not `none`.
135 bool HasAuthorSpecifiedBorderOrBackground() const {
136 return bool(Flags() & Flag::HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND);
139 // Does this ComputedStyle or any of its ancestors have text
140 // decoration lines?
141 // Differs from nsStyleTextReset::HasTextDecorationLines, which tests
142 // only the data for a single context.
143 bool HasTextDecorationLines() const {
144 return bool(Flags() & Flag::HAS_TEXT_DECORATION_LINES);
147 // Whether any line break inside should be suppressed? If this returns
148 // true, the line should not be broken inside, which means inlines act
149 // as if nowrap is set, <br> is suppressed, and blocks are inlinized.
150 // This bit is propogated to all children of line partitipants. It is
151 // currently used by ruby to make its content frames unbreakable.
152 // NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
153 // instead of this method.
154 bool ShouldSuppressLineBreak() const {
155 return bool(Flags() & Flag::SHOULD_SUPPRESS_LINEBREAK);
158 // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
159 // only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText().
160 bool IsTextCombined() const { return bool(Flags() & Flag::IS_TEXT_COMBINED); }
162 // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
163 // only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText().
164 bool DependsOnFontMetrics() const {
165 return bool(Flags() & Flag::DEPENDS_ON_FONT_METRICS);
168 // Does this ComputedStyle represent the style for a pseudo-element or
169 // inherit data from such a ComputedStyle? Whether this returns true
170 // is equivalent to whether it or any of its ancestors returns
171 // non-null for IsPseudoElement().
172 bool HasPseudoElementData() const {
173 return bool(Flags() & Flag::IS_IN_PSEUDO_ELEMENT_SUBTREE);
176 // Is the only link whose visitedness is allowed to influence the
177 // style of the node this ComputedStyle is for (which is that element
178 // or its nearest ancestor that is a link) visited?
179 bool RelevantLinkVisited() const {
180 return bool(Flags() & Flag::IS_RELEVANT_LINK_VISITED);
183 // Whether this style is for the root element of the document.
184 bool IsRootElementStyle() const {
185 return bool(Flags() & Flag::IS_ROOT_ELEMENT_STYLE);
188 bool IsInOpacityZeroSubtree() const {
189 return bool(Flags() & Flag::IS_IN_OPACITY_ZERO_SUBTREE);
192 ComputedStyle* GetCachedInheritingAnonBoxStyle(
193 PseudoStyleType aPseudoType) const {
194 MOZ_ASSERT(PseudoStyle::IsInheritingAnonBox(aPseudoType));
195 return mCachedInheritingStyles.Lookup(aPseudoType);
198 void SetCachedInheritedAnonBoxStyle(ComputedStyle* aStyle) {
199 mCachedInheritingStyles.Insert(aStyle);
202 ComputedStyle* GetCachedLazyPseudoStyle(PseudoStyleType aPseudo) const;
204 void SetCachedLazyPseudoStyle(ComputedStyle* aStyle) {
205 MOZ_ASSERT(aStyle->IsPseudoElement());
206 MOZ_ASSERT(!GetCachedLazyPseudoStyle(aStyle->GetPseudoType()));
207 MOZ_ASSERT(aStyle->IsLazilyCascadedPseudoElement());
209 // Since we're caching lazy pseudo styles on the ComputedValues of the
210 // originating element, we can assume that we either have the same
211 // originating element, or that they were at least similar enough to share
212 // the same ComputedValues, which means that they would match the same
213 // pseudo rules. This allows us to avoid matching selectors and checking
214 // the rule node before deciding to share.
216 // The one place this optimization breaks is with pseudo-elements that
217 // support state (like :hover). So we just avoid sharing in those cases.
218 if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(
219 aStyle->GetPseudoType())) {
220 return;
223 mCachedInheritingStyles.Insert(aStyle);
226 #define STYLE_STRUCT(name_) \
227 inline const nsStyle##name_* Style##name_() const MOZ_NONNULL_RETURN { \
228 return mSource.GetStyle##name_(); \
230 #include "nsStyleStructList.h"
231 #undef STYLE_STRUCT
234 * Compute the style changes needed during restyling when this style
235 * context is being replaced by aNewContext. (This is nonsymmetric since
236 * we optimize by skipping comparison for styles that have never been
237 * requested.)
239 * This method returns a change hint (see nsChangeHint.h). All change
240 * hints apply to the frame and its later continuations or ib-split
241 * siblings. Most (all of those except the "NotHandledForDescendants"
242 * hints) also apply to all descendants.
244 * aEqualStructs must not be null. Into it will be stored a bitfield
245 * representing which structs were compared to be non-equal.
247 * CSS Variables are not compared here. Instead, the caller is responsible for
248 * that when needed (basically only for elements).
250 nsChangeHint CalcStyleDifference(const ComputedStyle& aNewContext,
251 uint32_t* aEqualStructs) const;
253 #ifdef DEBUG
254 bool EqualForCachedAnonymousContentStyle(const ComputedStyle&) const;
255 #endif
257 public:
259 * Get a color that depends on link-visitedness using this and
260 * this->GetStyleIfVisited().
262 * @param aField A pointer to a member variable in a style struct.
263 * The member variable and its style struct must have
264 * been listed in nsCSSVisitedDependentPropList.h.
266 template <typename T, typename S>
267 nscolor GetVisitedDependentColor(T S::*aField) const;
270 * aColors should be a two element array of nscolor in which the first
271 * color is the unvisited color and the second is the visited color.
273 * Combine the R, G, and B components of whichever of aColors should
274 * be used based on aLinkIsVisited with the A component of aColors[0].
276 static nscolor CombineVisitedColors(nscolor* aColors, bool aLinkIsVisited);
279 * Start image loads for this style.
281 * The Document is used to get a hand on the image loader. The old style is a
282 * hack for bug 1439285.
284 inline void StartImageLoads(dom::Document&,
285 const ComputedStyle* aOldStyle = nullptr);
287 #ifdef DEBUG
288 void List(FILE* out, int32_t aIndent);
289 static const char* StructName(StyleStructID aSID);
290 static Maybe<StyleStructID> LookupStruct(const nsACString& aName);
291 #endif
293 // The |aCVsSize| outparam on this function is where the actual CVs size
294 // value is added. It's done that way because the callers know which value
295 // the size should be added to.
296 void AddSizeOfIncludingThis(nsWindowSizes& aSizes, size_t* aCVsSize) const;
298 StyleWritingMode WritingMode() const { return {mSource.WritingMode().mBits}; }
300 protected:
301 // Needs to be friend so that it can call the destructor without making it
302 // public.
303 friend void ::Gecko_ComputedStyle_Destroy(ComputedStyle*);
305 ~ComputedStyle() = default;
307 ServoComputedData mSource;
309 // A cache of anonymous box and lazy pseudo styles inheriting from this style.
310 CachedInheritingStyles mCachedInheritingStyles;
312 const PseudoStyleType mPseudoType;
315 } // namespace mozilla
317 #endif