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_ServoStyleSet_h
8 #define mozilla_ServoStyleSet_h
9 
10 #include "mozilla/EnumeratedArray.h"
11 #include "mozilla/EventStates.h"
12 #include "mozilla/ServoBindingTypes.h"
13 #include "mozilla/ServoElementSnapshot.h"
14 #include "mozilla/StyleSheetInlines.h"
15 #include "mozilla/SheetType.h"
16 #include "mozilla/UniquePtr.h"
17 #include "nsCSSPseudoElements.h"
18 #include "nsChangeHint.h"
19 #include "nsIAtom.h"
20 #include "nsTArray.h"
21 
22 namespace mozilla {
23 namespace dom {
24 class Element;
25 } // namespace dom
26 class CSSStyleSheet;
27 class ServoRestyleManager;
28 class ServoStyleSheet;
29 } // namespace mozilla
30 class nsIDocument;
31 class nsStyleContext;
32 class nsPresContext;
33 struct TreeMatchContext;
34 
35 namespace mozilla {
36 
37 /**
38  * The set of style sheets that apply to a document, backed by a Servo
39  * Stylist.  A ServoStyleSet contains ServoStyleSheets.
40  */
41 class ServoStyleSet
42 {
43   friend class ServoRestyleManager;
44 public:
45   ServoStyleSet();
46 
47   void Init(nsPresContext* aPresContext);
48   void BeginShutdown();
49   void Shutdown();
50 
51   bool GetAuthorStyleDisabled() const;
52   nsresult SetAuthorStyleDisabled(bool aStyleDisabled);
53 
54   void BeginUpdate();
55   nsresult EndUpdate();
56 
57   already_AddRefed<nsStyleContext>
58   ResolveStyleFor(dom::Element* aElement,
59                   nsStyleContext* aParentContext);
60 
61   already_AddRefed<nsStyleContext>
62   ResolveStyleFor(dom::Element* aElement,
63                   nsStyleContext* aParentContext,
64                   TreeMatchContext& aTreeMatchContext);
65 
66   already_AddRefed<nsStyleContext>
67   ResolveStyleForText(nsIContent* aTextNode,
68                       nsStyleContext* aParentContext);
69 
70   already_AddRefed<nsStyleContext>
71   ResolveStyleForOtherNonElement(nsStyleContext* aParentContext);
72 
73   already_AddRefed<nsStyleContext>
74   ResolvePseudoElementStyle(dom::Element* aParentElement,
75                             mozilla::CSSPseudoElementType aType,
76                             nsStyleContext* aParentContext,
77                             dom::Element* aPseudoElement);
78 
79   // aFlags is an nsStyleSet flags bitfield
80   already_AddRefed<nsStyleContext>
81   ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,
82                            uint32_t aFlags = 0);
83 
84   // manage the set of style sheets in the style set
85   nsresult AppendStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
86   nsresult PrependStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
87   nsresult RemoveStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
88   nsresult ReplaceSheets(SheetType aType,
89                          const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets);
90   nsresult InsertStyleSheetBefore(SheetType aType,
91                                   ServoStyleSheet* aNewSheet,
92                                   ServoStyleSheet* aReferenceSheet);
93 
94   int32_t SheetCount(SheetType aType) const;
95   ServoStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
96 
97   nsresult RemoveDocStyleSheet(ServoStyleSheet* aSheet);
98   nsresult AddDocStyleSheet(ServoStyleSheet* aSheet, nsIDocument* aDocument);
99 
100   // check whether there is ::before/::after style for an element
101   already_AddRefed<nsStyleContext>
102   ProbePseudoElementStyle(dom::Element* aParentElement,
103                           mozilla::CSSPseudoElementType aType,
104                           nsStyleContext* aParentContext);
105 
106   already_AddRefed<nsStyleContext>
107   ProbePseudoElementStyle(dom::Element* aParentElement,
108                           mozilla::CSSPseudoElementType aType,
109                           nsStyleContext* aParentContext,
110                           TreeMatchContext& aTreeMatchContext,
111                           dom::Element* aPseudoElement = nullptr);
112 
113   // Test if style is dependent on content state
114   nsRestyleHint HasStateDependentStyle(dom::Element* aElement,
115                                        EventStates aStateMask);
116   nsRestyleHint HasStateDependentStyle(
117     dom::Element* aElement, mozilla::CSSPseudoElementType aPseudoType,
118     dom::Element* aPseudoElement, EventStates aStateMask);
119 
120   /**
121    * Computes a restyle hint given a element and a previous element snapshot.
122    */
123   nsRestyleHint ComputeRestyleHint(dom::Element* aElement,
124                                    ServoElementSnapshot* aSnapshot);
125 
126   /**
127    * Performs a Servo traversal to compute style for all dirty nodes in the
128    * document. The root element must be non-null.
129    *
130    * If aLeaveDirtyBits is true, the dirty/dirty-descendant bits are not
131    * cleared.
132    */
133   void StyleDocument(bool aLeaveDirtyBits);
134 
135   /**
136    * Eagerly styles a subtree of dirty nodes that were just appended to the
137    * tree. This is used in situations where we need the style immediately and
138    * cannot wait for a future batch restyle.
139    *
140    * The subtree must have the root dirty bit set, which currently gets
141    * propagated to all descendants. The dirty bits are cleared before
142    * returning.
143    */
144   void StyleNewSubtree(nsIContent* aContent);
145 
146   /**
147    * Like the above, but does not assume that the root node is dirty. When
148    * appending multiple children to a potentially-non-dirty node, it's
149    * preferable to call StyleNewChildren on the node rather than making multiple
150    * calls to StyleNewSubtree on each child, since it allows for more
151    * parallelism.
152    */
153   void StyleNewChildren(nsIContent* aParent);
154 
155 private:
156   already_AddRefed<nsStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
157                                               nsStyleContext* aParentContext,
158                                               nsIAtom* aPseudoTag,
159                                               CSSPseudoElementType aPseudoType);
160 
161   already_AddRefed<nsStyleContext> GetContext(nsIContent* aContent,
162                                               nsStyleContext* aParentContext,
163                                               nsIAtom* aPseudoTag,
164                                               CSSPseudoElementType aPseudoType);
165 
166   nsPresContext* mPresContext;
167   UniquePtr<RawServoStyleSet> mRawSet;
168   EnumeratedArray<SheetType, SheetType::Count,
169                   nsTArray<RefPtr<ServoStyleSheet>>> mSheets;
170   int32_t mBatching;
171 };
172 
173 } // namespace mozilla
174 
175 #endif // mozilla_ServoStyleSet_h
176