Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / layout / style / ComputedStyle.h
blob5e2c10b8e418fcdc7b14dddd02d7f174d970ede7
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 "mozilla/Assertions.h"
13 #include "mozilla/CachedInheritingStyles.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/PseudoStyleType.h"
16 #include "mozilla/ServoComputedData.h"
17 #include "mozilla/ServoStyleConsts.h"
18 #include "nsCSSPseudoElements.h"
19 #include "nsColor.h"
21 #include "nsStyleStructFwd.h"
23 enum nsChangeHint : uint32_t;
24 class nsWindowSizes;
26 #define STYLE_STRUCT(name_) struct nsStyle##name_;
27 #include "nsStyleStructList.h"
28 #undef STYLE_STRUCT
30 extern "C" {
31 void Gecko_ComputedStyle_Destroy(mozilla::ComputedStyle*);
34 namespace mozilla {
36 enum class StylePointerEvents : uint8_t;
37 enum class StyleUserSelect : uint8_t;
39 namespace dom {
40 class Document;
43 /**
44 * A ComputedStyle represents the computed style data for an element.
46 * The computed style data are stored in a set of reference counted structs
47 * (see nsStyleStruct.h) that are stored directly on the ComputedStyle.
49 * Style structs are immutable once they have been produced, so when any change
50 * is made that needs a restyle, we create a new ComputedStyle.
52 * ComputedStyles are reference counted. References are generally held by:
54 * 1. nsIFrame::mComputedStyle, for every frame
55 * 2. Element::mServoData, for every element not inside a display:none subtree
56 * 3. nsComputedDOMStyle, when created for elements in display:none subtrees
57 * 4. media_queries::Device, which holds the initial value of every property
60 class ComputedStyle {
61 using Flag = StyleComputedValueFlags;
63 const StyleComputedValueFlags& Flags() const { return mSource.flags; }
65 public:
66 ComputedStyle(PseudoStyleType aPseudoType,
67 ServoComputedDataForgotten aComputedValues);
69 // Returns the computed (not resolved) value of the given property.
70 void GetComputedPropertyValue(nsCSSPropertyID aId, nsACString& aOut) const {
71 Servo_GetComputedValue(this, aId, &aOut);
74 // Return the ComputedStyle whose style data should be used for the R,
75 // G, and B components of color, background-color, and border-*-color
76 // if RelevantLinkIsVisited().
78 // GetPseudo() and GetPseudoType() on this ComputedStyle return the
79 // same as on |this|, and its depth in the tree (number of GetParent()
80 // calls until null is returned) is the same as |this|, since its
81 // parent is either |this|'s parent or |this|'s parent's
82 // style-if-visited.
84 // Structs on this context should never be examined without also
85 // examining the corresponding struct on |this|. Doing so will likely
86 // both (1) lead to a privacy leak and (2) lead to dynamic change bugs
87 // related to the Peek code in ComputedStyle::CalcStyleDifference.
88 const ComputedStyle* GetStyleIfVisited() const {
89 return mSource.visited_style;
92 bool IsLazilyCascadedPseudoElement() const {
93 return IsPseudoElement() &&
94 !nsCSSPseudoElements::IsEagerlyCascadedInServo(GetPseudoType());
97 PseudoStyleType GetPseudoType() const { return mPseudoType; }
99 bool IsPseudoElement() const {
100 return PseudoStyle::IsPseudoElement(mPseudoType);
103 bool IsInheritingAnonBox() const {
104 return PseudoStyle::IsInheritingAnonBox(mPseudoType);
107 bool IsNonInheritingAnonBox() const {
108 return PseudoStyle::IsNonInheritingAnonBox(mPseudoType);
111 bool IsWrapperAnonBox() const {
112 return PseudoStyle::IsWrapperAnonBox(mPseudoType);
115 bool IsAnonBox() const { return PseudoStyle::IsAnonBox(mPseudoType); }
117 bool IsPseudoOrAnonBox() const {
118 return mPseudoType != PseudoStyleType::NotPseudo;
121 // Whether there are author-specified rules for border or background
122 // properties.
123 // Only returns something meaningful if the appearance property is not `none`.
124 bool HasAuthorSpecifiedBorderOrBackground() const {
125 return bool(Flags() & Flag::HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND);
128 // Whether there are author-specific rules for text color.
129 bool HasAuthorSpecifiedTextColor() const {
130 return bool(Flags() & Flag::HAS_AUTHOR_SPECIFIED_TEXT_COLOR);
133 // Does this ComputedStyle or any of its ancestors have text
134 // decoration lines?
135 // Differs from nsStyleTextReset::HasTextDecorationLines, which tests
136 // only the data for a single context.
137 bool HasTextDecorationLines() const {
138 return bool(Flags() & Flag::HAS_TEXT_DECORATION_LINES);
141 // Whether any line break inside should be suppressed? If this returns
142 // true, the line should not be broken inside, which means inlines act
143 // as if nowrap is set, <br> is suppressed, and blocks are inlinized.
144 // This bit is propogated to all children of line partitipants. It is
145 // currently used by ruby to make its content frames unbreakable.
146 // NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
147 // instead of this method.
148 bool ShouldSuppressLineBreak() const {
149 return bool(Flags() & Flag::SHOULD_SUPPRESS_LINEBREAK);
152 // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
153 // only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText().
154 bool IsTextCombined() const { return bool(Flags() & Flag::IS_TEXT_COMBINED); }
156 // Whether there's any font metric dependency coming directly from our style.
157 bool DependsOnSelfFontMetrics() const {
158 return bool(Flags() & Flag::DEPENDS_ON_SELF_FONT_METRICS);
161 // Whether there's any font metric dependency coming directly from our parent
162 // style.
163 bool DependsOnInheritedFontMetrics() const {
164 return bool(Flags() & Flag::DEPENDS_ON_INHERITED_FONT_METRICS);
167 // Does this ComputedStyle represent the style for a pseudo-element or
168 // inherit data from such a ComputedStyle? Whether this returns true
169 // is equivalent to whether it or any of its ancestors returns
170 // non-null for IsPseudoElement().
171 bool HasPseudoElementData() const {
172 return bool(Flags() & Flag::IS_IN_PSEUDO_ELEMENT_SUBTREE);
175 bool SelfOrAncestorHasContainStyle() const {
176 return bool(Flags() & Flag::SELF_OR_ANCESTOR_HAS_CONTAIN_STYLE);
179 // Is the only link whose visitedness is allowed to influence the
180 // style of the node this ComputedStyle is for (which is that element
181 // or its nearest ancestor that is a link) visited?
182 bool RelevantLinkVisited() const {
183 return bool(Flags() & Flag::IS_RELEVANT_LINK_VISITED);
186 // Whether this style is for the root element of the document.
187 bool IsRootElementStyle() const {
188 return bool(Flags() & Flag::IS_ROOT_ELEMENT_STYLE);
191 bool IsInOpacityZeroSubtree() const {
192 return bool(Flags() & Flag::IS_IN_OPACITY_ZERO_SUBTREE);
195 ComputedStyle* GetCachedInheritingAnonBoxStyle(
196 PseudoStyleType aPseudoType) const {
197 MOZ_ASSERT(PseudoStyle::IsInheritingAnonBox(aPseudoType));
198 return mCachedInheritingStyles.Lookup(aPseudoType);
201 void SetCachedInheritedAnonBoxStyle(ComputedStyle* aStyle) {
202 mCachedInheritingStyles.Insert(aStyle);
205 ComputedStyle* GetCachedLazyPseudoStyle(PseudoStyleType aPseudo) const;
207 void SetCachedLazyPseudoStyle(ComputedStyle* aStyle) {
208 MOZ_ASSERT(aStyle->IsPseudoElement());
209 MOZ_ASSERT(!GetCachedLazyPseudoStyle(aStyle->GetPseudoType()));
210 MOZ_ASSERT(aStyle->IsLazilyCascadedPseudoElement());
212 // Since we're caching lazy pseudo styles on the ComputedValues of the
213 // originating element, we can assume that we either have the same
214 // originating element, or that they were at least similar enough to share
215 // the same ComputedValues, which means that they would match the same
216 // pseudo rules. This allows us to avoid matching selectors and checking
217 // the rule node before deciding to share.
219 // The one place this optimization breaks is with pseudo-elements that
220 // support state (like :hover). So we just avoid sharing in those cases.
221 if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(
222 aStyle->GetPseudoType())) {
223 return;
226 mCachedInheritingStyles.Insert(aStyle);
229 #define STYLE_STRUCT(name_) \
230 inline const nsStyle##name_* Style##name_() const MOZ_NONNULL_RETURN { \
231 return mSource.Style##name_(); \
233 #include "nsStyleStructList.h"
234 #undef STYLE_STRUCT
236 inline mozilla::StylePointerEvents PointerEvents() const;
237 inline mozilla::StyleUserSelect UserSelect() const;
240 * Returns whether the element is a containing block for its absolutely
241 * positioned descendants.
242 * aContextFrame is the frame for which this is the style (or an old style).
244 inline bool IsAbsPosContainingBlock(const nsIFrame*) const;
247 * Returns true when the element is a containing block for its fixed-pos
248 * descendants.
249 * aContextFrame is the frame for which this is the style (or an old style).
251 inline bool IsFixedPosContainingBlock(const nsIFrame*) const;
254 * Tests for only the sub-parts of IsFixedPosContainingBlock that apply to:
255 * - nearly all frames, except those that are in SVG text subtrees.
256 * - frames that support CSS contain:layout and contain:paint and are not
257 * in SVG text subtrees.
258 * - frames that support CSS transforms and are not in SVG text subtrees.
260 * This should be used only when the caller has the style but not the
261 * frame (i.e., when calculating style changes).
263 inline bool IsFixedPosContainingBlockForNonSVGTextFrames() const;
266 * Compute the style changes needed during restyling when this style
267 * context is being replaced by aNewContext. (This is nonsymmetric since
268 * we optimize by skipping comparison for styles that have never been
269 * requested.)
271 * This method returns a change hint (see nsChangeHint.h). All change
272 * hints apply to the frame and its later continuations or ib-split
273 * siblings. Most (all of those except the "NotHandledForDescendants"
274 * hints) also apply to all descendants.
276 * aEqualStructs must not be null. Into it will be stored a bitfield
277 * representing which structs were compared to be non-equal.
279 * CSS Variables are not compared here. Instead, the caller is responsible for
280 * that when needed (basically only for elements).
282 nsChangeHint CalcStyleDifference(const ComputedStyle& aNewContext,
283 uint32_t* aEqualStructs) const;
285 #ifdef DEBUG
286 bool EqualForCachedAnonymousContentStyle(const ComputedStyle&) const;
287 #endif
289 #ifdef DEBUG
290 void DumpMatchedRules() const;
291 #endif
294 * Get a color that depends on link-visitedness using this and
295 * this->GetStyleIfVisited().
297 * @param aField A pointer to a member variable in a style struct.
298 * The member variable and its style struct must have
299 * been listed in nsCSSVisitedDependentPropList.h.
301 template <typename T, typename S>
302 nscolor GetVisitedDependentColor(T S::*aField) const;
305 * aColors should be a two element array of nscolor in which the first
306 * color is the unvisited color and the second is the visited color.
308 * Combine the R, G, and B components of whichever of aColors should
309 * be used based on aLinkIsVisited with the A component of aColors[0].
311 static nscolor CombineVisitedColors(nscolor* aColors, bool aLinkIsVisited);
314 * Start image loads for this style.
316 * The Document is used to get a hand on the image loader. The old style is a
317 * hack for bug 1439285.
319 inline void StartImageLoads(dom::Document&,
320 const ComputedStyle* aOldStyle = nullptr);
322 #ifdef DEBUG
323 void List(FILE* out, int32_t aIndent);
324 static const char* StructName(StyleStructID aSID);
325 static Maybe<StyleStructID> LookupStruct(const nsACString& aName);
326 #endif
328 // The |aCVsSize| outparam on this function is where the actual CVs size
329 // value is added. It's done that way because the callers know which value
330 // the size should be added to.
331 void AddSizeOfIncludingThis(nsWindowSizes& aSizes, size_t* aCVsSize) const;
333 StyleWritingMode WritingMode() const { return {mSource.WritingMode().mBits}; }
335 protected:
336 // Needs to be friend so that it can call the destructor without making it
337 // public.
338 friend void ::Gecko_ComputedStyle_Destroy(ComputedStyle*);
340 ~ComputedStyle() = default;
342 ServoComputedData mSource;
344 // A cache of anonymous box and lazy pseudo styles inheriting from this style.
345 CachedInheritingStyles mCachedInheritingStyles;
347 const PseudoStyleType mPseudoType;
350 } // namespace mozilla
352 #endif