Line data Source code
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 : #ifndef mozilla_GeckoStyleContext_h
8 : #define mozilla_GeckoStyleContext_h
9 :
10 : #include "nsStyleContext.h"
11 :
12 : namespace mozilla {
13 :
14 : class GeckoStyleContext final : public nsStyleContext {
15 : public:
16 : GeckoStyleContext(nsStyleContext* aParent,
17 : nsIAtom* aPseudoTag,
18 : CSSPseudoElementType aPseudoType,
19 : already_AddRefed<nsRuleNode> aRuleNode,
20 : bool aSkipParentDisplayBasedStyleFixup);
21 :
22 : void* operator new(size_t sz, nsPresContext* aPresContext);
23 :
24 76305 : nsPresContext* PresContext() const {
25 76305 : return RuleNode()->PresContext();
26 : }
27 :
28 : void AddChild(GeckoStyleContext* aChild);
29 : void RemoveChild(GeckoStyleContext* aChild);
30 :
31 : void* GetUniqueStyleData(const nsStyleStructID& aSID);
32 : void* CreateEmptyStyleData(const nsStyleStructID& aSID);
33 :
34 : /**
35 : * Ensures the same structs are cached on this style context as would be
36 : * done if we called aOther->CalcDifference(this).
37 : */
38 : void EnsureSameStructsCached(nsStyleContext* aOldContext);
39 :
40 : /**
41 : * Sets the NS_STYLE_INELIGIBLE_FOR_SHARING bit on this style context
42 : * and its descendants. If it finds a descendant that has the bit
43 : * already set, assumes that it can skip that subtree.
44 : */
45 : void SetIneligibleForSharing();
46 : /**
47 : * On each descendant of this style context, clears out any cached inherited
48 : * structs indicated in aStructs.
49 : */
50 : void ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
51 : // Find, if it already exists *and is easily findable* (i.e., near the
52 : // start of the child list), a style context whose:
53 : // * GetPseudo() matches aPseudoTag
54 : // * mRuleNode matches aSource
55 : // * !!GetStyleIfVisited() == !!aSourceIfVisited, and, if they're
56 : // non-null, GetStyleIfVisited()->mRuleNode == aSourceIfVisited
57 : // * RelevantLinkVisited() == aRelevantLinkVisited
58 : already_AddRefed<GeckoStyleContext>
59 : FindChildWithRules(const nsIAtom* aPseudoTag,
60 : nsRuleNode* aSource,
61 : nsRuleNode* aSourceIfVisited,
62 : bool aRelevantLinkVisited);
63 :
64 : // Tell this style context to cache aStruct as the struct for aSID
65 : void SetStyle(nsStyleStructID aSID, void* aStruct);
66 :
67 :
68 : /*
69 : * Get the style data for a style struct. This is the most important
70 : * member function of nsStyleContext. It fills in a const pointer
71 : * to a style data struct that is appropriate for the style context's
72 : * frame. This struct may be shared with other contexts (either in
73 : * the rule tree or the style context tree), so it should not be
74 : * modified.
75 : *
76 : * This function will NOT return null (even when out of memory) when
77 : * given a valid style struct ID, so the result does not need to be
78 : * null-checked.
79 : *
80 : * The typesafe functions below are preferred to the use of this
81 : * function, both because they're easier to read and because they're
82 : * faster.
83 : */
84 : const void* NS_FASTCALL StyleData(nsStyleStructID aSID) MOZ_NONNULL_RETURN;
85 :
86 : #ifdef DEBUG
87 : void ListDescendants(FILE* out, int32_t aIndent);
88 :
89 : #endif
90 :
91 : #ifdef RESTYLE_LOGGING
92 :
93 : // This only gets called under call trees where we've already checked
94 : // that PresContext()->RestyleManager()->ShouldLogRestyle() returned true.
95 : // It exists here just to satisfy LOG_RESTYLE's expectations.
96 0 : bool ShouldLogRestyle() { return true; }
97 : void LogStyleContextTree(int32_t aLoggingDepth, uint32_t aStructs);
98 : void LogStyleContextTree(bool aFirst, uint32_t aStructs);
99 : int32_t& LoggingDepth();
100 : nsCString GetCachedStyleDataAsString(uint32_t aStructs);
101 : #endif
102 :
103 : // Only called for Gecko-backed nsStyleContexts.
104 : void ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup);
105 :
106 : bool HasNoChildren() const;
107 :
108 380527 : nsRuleNode* RuleNode() const {
109 380527 : MOZ_ASSERT(mRuleNode);
110 380527 : return mRuleNode;
111 : }
112 :
113 3236 : ~GeckoStyleContext() {
114 1618 : Destructor();
115 1618 : }
116 :
117 : /**
118 : * Swaps owned style struct pointers between this and aNewContext, on
119 : * the assumption that aNewContext is the new style context for a frame
120 : * and this is the old one. aStructs indicates which structs to consider
121 : * swapping; only those which are owned in both this and aNewContext
122 : * will be swapped.
123 : *
124 : * Additionally, if there are identical struct pointers for one of the
125 : * structs indicated by aStructs, and it is not an owned struct on this,
126 : * then the cached struct slot on this will be set to null. If the struct
127 : * has been swapped on an ancestor, this style context (being the old one)
128 : * will be left caching the struct pointer on the new ancestor, despite
129 : * inheriting from the old ancestor. This is not normally a problem, as
130 : * this style context will usually be destroyed by being released at the
131 : * end of ElementRestyler::Restyle; but for style contexts held on to outside
132 : * of the frame, we need to clear out the cached pointer so that if we need
133 : * it again we'll re-fetch it from the new ancestor.
134 : */
135 : void SwapStyleData(GeckoStyleContext* aNewContext, uint32_t aStructs);
136 :
137 : void DestroyCachedStructs(nsPresContext* aPresContext);
138 :
139 : /**
140 : * Return style data that is currently cached on the style context.
141 : * Only returns the structs we cache ourselves; never consults the
142 : * rule tree.
143 : *
144 : * For "internal" use only in nsStyleContext and nsRuleNode.
145 : */
146 291591 : const void* GetCachedStyleData(nsStyleStructID aSID)
147 : {
148 : const void* cachedData;
149 291591 : if (nsCachedStyleData::IsReset(aSID)) {
150 283075 : if (mCachedResetData) {
151 173481 : cachedData = mCachedResetData->mStyleStructs[aSID];
152 : } else {
153 109594 : cachedData = nullptr;
154 : }
155 : } else {
156 8516 : cachedData = mCachedInheritedData.mStyleStructs[aSID];
157 : }
158 291591 : return cachedData;
159 : }
160 :
161 : // mCachedInheritedData and mCachedResetData point to both structs that
162 : // are owned by this style context and structs that are owned by one of
163 : // this style context's ancestors (which are indirectly owned since this
164 : // style context owns a reference to its parent). If the bit in |mBits|
165 : // is set for a struct, that means that the pointer for that struct is
166 : // owned by an ancestor or by the rule node rather than by this style context.
167 : // Since style contexts typically have some inherited data but only sometimes
168 : // have reset data, we always allocate the mCachedInheritedData, but only
169 : // sometimes allocate the mCachedResetData.
170 : nsResetStyleData* mCachedResetData; // Cached reset style data.
171 : nsInheritedStyleData mCachedInheritedData; // Cached inherited style data
172 :
173 : #ifdef DEBUG
174 : void AssertStructsNotUsedElsewhere(GeckoStyleContext* aDestroyingContext,
175 : int32_t aLevels) const;
176 : #endif
177 :
178 : private:
179 : // Helper for ClearCachedInheritedStyleDataOnDescendants.
180 : void DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
181 :
182 : // Children are kept in two circularly-linked lists. The list anchor
183 : // is not part of the list (null for empty), and we point to the first
184 : // child.
185 : // mEmptyChild for children whose rule node is the root rule node, and
186 : // mChild for other children. The order of children is not
187 : // meaningful.
188 : GeckoStyleContext* mChild;
189 : GeckoStyleContext* mEmptyChild;
190 : GeckoStyleContext* mPrevSibling;
191 : GeckoStyleContext* mNextSibling;
192 : RefPtr<nsRuleNode> mRuleNode;
193 :
194 : #ifdef DEBUG
195 : public:
196 : struct AutoCheckDependency {
197 :
198 : GeckoStyleContext* mStyleContext;
199 : nsStyleStructID mOuterSID;
200 :
201 286889 : AutoCheckDependency(GeckoStyleContext* aContext, nsStyleStructID aInnerSID)
202 286889 : : mStyleContext(aContext)
203 : {
204 286889 : mOuterSID = aContext->mComputingStruct;
205 286889 : MOZ_ASSERT(mOuterSID == nsStyleStructID_None ||
206 : DependencyAllowed(mOuterSID, aInnerSID),
207 : "Undeclared dependency, see generate-stylestructlist.py");
208 286889 : aContext->mComputingStruct = aInnerSID;
209 286889 : }
210 :
211 286889 : ~AutoCheckDependency()
212 286889 : {
213 286889 : mStyleContext->mComputingStruct = mOuterSID;
214 286889 : }
215 :
216 : };
217 :
218 : private:
219 : // Used to check for undeclared dependencies.
220 : // See AUTO_CHECK_DEPENDENCY in nsStyleContextInlines.h.
221 : nsStyleStructID mComputingStruct;
222 :
223 : #define AUTO_CHECK_DEPENDENCY(gecko_, sid_) \
224 : mozilla::GeckoStyleContext::AutoCheckDependency checkNesting_(gecko_, sid_)
225 : #else
226 : #define AUTO_CHECK_DEPENDENCY(gecko_, sid_)
227 : #endif
228 : };
229 : }
230 :
231 : #endif // mozilla_GeckoStyleContext_h
|