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_StyleSetHandle_h
8 : #define mozilla_StyleSetHandle_h
9 :
10 : #include "mozilla/EventStates.h"
11 : #include "mozilla/RefPtr.h"
12 : #include "mozilla/ServoTypes.h"
13 : #include "mozilla/SheetType.h"
14 : #include "mozilla/StyleBackendType.h"
15 : #include "mozilla/StyleSheet.h"
16 : #include "nsChangeHint.h"
17 : #include "nsCSSPseudoElements.h"
18 : #include "nsTArray.h"
19 :
20 : namespace mozilla {
21 : class CSSStyleSheet;
22 : class ServoStyleSet;
23 : namespace dom {
24 : class Element;
25 : class ShadowRoot;
26 : } // namespace dom
27 : } // namespace mozilla
28 : class nsBindingManager;
29 : class nsCSSCounterStyleRule;
30 : struct nsFontFaceRuleContainer;
31 : class nsIAtom;
32 : class nsIContent;
33 : class nsIDocument;
34 : class nsStyleContext;
35 : class nsStyleSet;
36 : class nsPresContext;
37 : struct TreeMatchContext;
38 :
39 : namespace mozilla {
40 :
41 : #define SERVO_BIT 0x1
42 :
43 : /**
44 : * Smart pointer class that can hold a pointer to either an nsStyleSet
45 : * or a ServoStyleSet.
46 : */
47 : class StyleSetHandle
48 : {
49 : public:
50 : // We define this Ptr class with a StyleSet API that forwards on to the
51 : // wrapped pointer, rather than putting these methods on StyleSetHandle
52 : // itself, so that we can have StyleSetHandle behave like a smart pointer and
53 : // be dereferenced with operator->.
54 : class Ptr
55 : {
56 : public:
57 : friend class ::mozilla::StyleSetHandle;
58 :
59 27552 : bool IsGecko() const { return !IsServo(); }
60 28366 : bool IsServo() const
61 : {
62 28366 : MOZ_ASSERT(mValue, "StyleSetHandle null pointer dereference");
63 : #ifdef MOZ_STYLO
64 : return mValue & SERVO_BIT;
65 : #else
66 28366 : return false;
67 : #endif
68 : }
69 :
70 65 : StyleBackendType BackendType() const
71 : {
72 65 : return IsGecko() ? StyleBackendType::Gecko :
73 65 : StyleBackendType::Servo;
74 : }
75 :
76 13708 : nsStyleSet* AsGecko()
77 : {
78 13708 : MOZ_ASSERT(IsGecko());
79 13708 : return reinterpret_cast<nsStyleSet*>(mValue);
80 : }
81 :
82 0 : ServoStyleSet* AsServo()
83 : {
84 0 : MOZ_ASSERT(IsServo());
85 0 : return reinterpret_cast<ServoStyleSet*>(mValue & ~SERVO_BIT);
86 : }
87 :
88 1704 : nsStyleSet* GetAsGecko() { return IsGecko() ? AsGecko() : nullptr; }
89 720 : ServoStyleSet* GetAsServo() { return IsServo() ? AsServo() : nullptr; }
90 :
91 100 : const nsStyleSet* AsGecko() const
92 : {
93 100 : return const_cast<Ptr*>(this)->AsGecko();
94 : }
95 :
96 0 : const ServoStyleSet* AsServo() const
97 : {
98 0 : MOZ_ASSERT(IsServo());
99 0 : return const_cast<Ptr*>(this)->AsServo();
100 : }
101 :
102 : const nsStyleSet* GetAsGecko() const { return IsGecko() ? AsGecko() : nullptr; }
103 : const ServoStyleSet* GetAsServo() const { return IsServo() ? AsServo() : nullptr; }
104 :
105 : // These inline methods are defined in StyleSetHandleInlines.h.
106 : inline void Delete();
107 :
108 : // Style set interface. These inline methods are defined in
109 : // StyleSetHandleInlines.h and just forward to the underlying
110 : // nsStyleSet or ServoStyleSet. See corresponding comments in
111 : // nsStyleSet.h for descriptions of these methods.
112 :
113 : inline void Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager);
114 : inline void BeginShutdown();
115 : inline void Shutdown();
116 : inline bool GetAuthorStyleDisabled() const;
117 : inline nsresult SetAuthorStyleDisabled(bool aStyleDisabled);
118 : inline void BeginUpdate();
119 : inline nsresult EndUpdate();
120 : inline already_AddRefed<nsStyleContext>
121 : ResolveStyleFor(dom::Element* aElement,
122 : nsStyleContext* aParentContext,
123 : LazyComputeBehavior aMayCompute);
124 : inline already_AddRefed<nsStyleContext>
125 : ResolveStyleFor(dom::Element* aElement,
126 : nsStyleContext* aParentContext,
127 : LazyComputeBehavior aMayCompute,
128 : TreeMatchContext* aTreeMatchContext);
129 : inline already_AddRefed<nsStyleContext>
130 : ResolveStyleForText(nsIContent* aTextNode,
131 : nsStyleContext* aParentContext);
132 : inline already_AddRefed<nsStyleContext>
133 : ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext);
134 : inline already_AddRefed<nsStyleContext>
135 : ResolveStyleForPlaceholder();
136 : inline already_AddRefed<nsStyleContext>
137 : ResolvePseudoElementStyle(dom::Element* aParentElement,
138 : mozilla::CSSPseudoElementType aType,
139 : nsStyleContext* aParentContext,
140 : dom::Element* aPseudoElement);
141 : inline already_AddRefed<nsStyleContext>
142 : ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
143 : nsStyleContext* aParentContext);
144 : inline already_AddRefed<nsStyleContext>
145 : ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag);
146 : inline nsresult AppendStyleSheet(SheetType aType, StyleSheet* aSheet);
147 : inline nsresult PrependStyleSheet(SheetType aType, StyleSheet* aSheet);
148 : inline nsresult RemoveStyleSheet(SheetType aType, StyleSheet* aSheet);
149 : inline nsresult ReplaceSheets(SheetType aType,
150 : const nsTArray<RefPtr<StyleSheet>>& aNewSheets);
151 : inline nsresult InsertStyleSheetBefore(SheetType aType,
152 : StyleSheet* aNewSheet,
153 : StyleSheet* aReferenceSheet);
154 : inline int32_t SheetCount(SheetType aType) const;
155 : inline StyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
156 : inline void AppendAllXBLStyleSheets(nsTArray<StyleSheet*>& aArray) const;
157 : inline nsresult RemoveDocStyleSheet(StyleSheet* aSheet);
158 : inline nsresult AddDocStyleSheet(StyleSheet* aSheet, nsIDocument* aDocument);
159 : inline void RecordStyleSheetChange(StyleSheet* aSheet, StyleSheet::ChangeType);
160 : inline void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
161 : inline bool StyleSheetsHaveChanged() const;
162 : inline void InvalidateStyleForCSSRuleChanges();
163 : inline bool MediumFeaturesChanged();
164 : inline already_AddRefed<nsStyleContext>
165 : ProbePseudoElementStyle(dom::Element* aParentElement,
166 : mozilla::CSSPseudoElementType aType,
167 : nsStyleContext* aParentContext);
168 : inline already_AddRefed<nsStyleContext>
169 : ProbePseudoElementStyle(dom::Element* aParentElement,
170 : mozilla::CSSPseudoElementType aType,
171 : nsStyleContext* aParentContext,
172 : TreeMatchContext* aTreeMatchContext);
173 : inline nsRestyleHint HasStateDependentStyle(dom::Element* aElement,
174 : EventStates aStateMask);
175 : inline nsRestyleHint HasStateDependentStyle(
176 : dom::Element* aElement,
177 : mozilla::CSSPseudoElementType aPseudoType,
178 : dom::Element* aPseudoElement,
179 : EventStates aStateMask);
180 :
181 : inline void RootStyleContextAdded();
182 : inline void RootStyleContextRemoved();
183 :
184 : inline bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
185 : inline nsCSSCounterStyleRule* CounterStyleRuleForName(nsIAtom* aName);
186 :
187 : inline bool EnsureUniqueInnerOnCSSSheets();
188 : inline void SetNeedsRestyleAfterEnsureUniqueInner();
189 :
190 : private:
191 : // Stores a pointer to an nsStyleSet or a ServoStyleSet. The least
192 : // significant bit is 0 for the former, 1 for the latter. This is
193 : // valid as the least significant bit will never be used for a pointer
194 : // value on platforms we care about.
195 : uintptr_t mValue;
196 : };
197 :
198 56 : StyleSetHandle() { mPtr.mValue = 0; }
199 22528 : StyleSetHandle(const StyleSetHandle& aOth) { mPtr.mValue = aOth.mPtr.mValue; }
200 165 : MOZ_IMPLICIT StyleSetHandle(nsStyleSet* aSet) { *this = aSet; }
201 0 : MOZ_IMPLICIT StyleSetHandle(ServoStyleSet* aSet) { *this = aSet; }
202 :
203 193 : StyleSetHandle& operator=(nsStyleSet* aStyleSet)
204 : {
205 193 : MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aStyleSet) & SERVO_BIT),
206 : "least significant bit shouldn't be set; we use it for state");
207 193 : mPtr.mValue = reinterpret_cast<uintptr_t>(aStyleSet);
208 193 : return *this;
209 : }
210 :
211 0 : StyleSetHandle& operator=(ServoStyleSet* aStyleSet)
212 : {
213 : #ifdef MOZ_STYLO
214 : MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aStyleSet) & SERVO_BIT),
215 : "least significant bit shouldn't be set; we use it for state");
216 : mPtr.mValue =
217 : aStyleSet ? (reinterpret_cast<uintptr_t>(aStyleSet) | SERVO_BIT) : 0;
218 : return *this;
219 : #else
220 0 : MOZ_CRASH("should not have a ServoStyleSet object when MOZ_STYLO is "
221 : "disabled");
222 : #endif
223 : }
224 :
225 : // Make StyleSetHandle usable in boolean contexts.
226 0 : explicit operator bool() const { return !!mPtr.mValue; }
227 79 : bool operator!() const { return !mPtr.mValue; }
228 439 : bool operator==(const StyleSetHandle& aOth) const
229 : {
230 439 : return mPtr.mValue == aOth.mPtr.mValue;
231 : }
232 : bool operator!=(const StyleSetHandle& aOth) const { return !(*this == aOth); }
233 :
234 : // Make StyleSetHandle behave like a smart pointer.
235 22827 : Ptr* operator->() { return &mPtr; }
236 7 : const Ptr* operator->() const { return &mPtr; }
237 :
238 : private:
239 : Ptr mPtr;
240 : };
241 :
242 : #undef SERVO_BIT
243 :
244 : } // namespace mozilla
245 :
246 : #endif // mozilla_StyleSetHandle_h
|