1 /*
2 * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 David Smith <catfish.man@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #ifndef ElementRareData_h
23 #define ElementRareData_h
24
25 #include "core/animation/ActiveAnimations.h"
26 #include "core/dom/DatasetDOMStringMap.h"
27 #include "core/dom/NamedNodeMap.h"
28 #include "core/dom/NodeRareData.h"
29 #include "core/dom/PseudoElement.h"
30 #include "core/dom/shadow/ElementShadow.h"
31 #include "core/html/ClassList.h"
32 #include "core/html/ime/InputMethodContext.h"
33 #include "core/rendering/style/StyleInheritedData.h"
34 #include "wtf/OwnPtr.h"
35
36 namespace WebCore {
37
38 class HTMLElement;
39
40 class ElementRareData : public NodeRareData {
41 public:
create(RenderObject * renderer)42 static PassOwnPtr<ElementRareData> create(RenderObject* renderer) { return adoptPtr(new ElementRareData(renderer)); }
43
44 ~ElementRareData();
45
46 void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
47 PseudoElement* pseudoElement(PseudoId) const;
48
49 void resetStyleState();
50 void resetDynamicRestyleObservations();
51
tabIndex()52 short tabIndex() const { return m_tabIndex; }
setTabIndexExplicitly(short index)53 void setTabIndexExplicitly(short index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; }
tabIndexSetExplicitly()54 bool tabIndexSetExplicitly() const { return m_tabIndexWasSetExplicitly; }
clearTabIndexExplicitly()55 void clearTabIndexExplicitly() { m_tabIndex = 0; m_tabIndexWasSetExplicitly = false; }
56
needsFocusAppearanceUpdateSoonAfterAttach()57 bool needsFocusAppearanceUpdateSoonAfterAttach() const { return m_needsFocusAppearanceUpdateSoonAfterAttach; }
setNeedsFocusAppearanceUpdateSoonAfterAttach(bool needs)58 void setNeedsFocusAppearanceUpdateSoonAfterAttach(bool needs) { m_needsFocusAppearanceUpdateSoonAfterAttach = needs; }
59
styleAffectedByEmpty()60 bool styleAffectedByEmpty() const { return m_styleAffectedByEmpty; }
setStyleAffectedByEmpty(bool value)61 void setStyleAffectedByEmpty(bool value) { m_styleAffectedByEmpty = value; }
62
isInCanvasSubtree()63 bool isInCanvasSubtree() const { return m_isInCanvasSubtree; }
setIsInCanvasSubtree(bool value)64 void setIsInCanvasSubtree(bool value) { m_isInCanvasSubtree = value; }
65
isInsideRegion()66 bool isInsideRegion() const { return m_isInsideRegion; }
setIsInsideRegion(bool value)67 void setIsInsideRegion(bool value) { m_isInsideRegion = value; }
68
regionOversetState()69 RegionOversetState regionOversetState() const { return m_regionOversetState; }
setRegionOversetState(RegionOversetState state)70 void setRegionOversetState(RegionOversetState state) { m_regionOversetState = state; }
71
containsFullScreenElement()72 bool containsFullScreenElement() { return m_containsFullScreenElement; }
setContainsFullScreenElement(bool value)73 void setContainsFullScreenElement(bool value) { m_containsFullScreenElement = value; }
74
isInTopLayer()75 bool isInTopLayer() const { return m_isInTopLayer; }
setIsInTopLayer(bool value)76 void setIsInTopLayer(bool value) { m_isInTopLayer = value; }
77
childrenAffectedByFocus()78 bool childrenAffectedByFocus() const { return m_childrenAffectedByFocus; }
setChildrenAffectedByFocus(bool value)79 void setChildrenAffectedByFocus(bool value) { m_childrenAffectedByFocus = value; }
childrenAffectedByHover()80 bool childrenAffectedByHover() const { return m_childrenAffectedByHover; }
setChildrenAffectedByHover(bool value)81 void setChildrenAffectedByHover(bool value) { m_childrenAffectedByHover = value; }
childrenAffectedByActive()82 bool childrenAffectedByActive() const { return m_childrenAffectedByActive; }
setChildrenAffectedByActive(bool value)83 void setChildrenAffectedByActive(bool value) { m_childrenAffectedByActive = value; }
childrenAffectedByDrag()84 bool childrenAffectedByDrag() const { return m_childrenAffectedByDrag; }
setChildrenAffectedByDrag(bool value)85 void setChildrenAffectedByDrag(bool value) { m_childrenAffectedByDrag = value; }
86
childrenAffectedByFirstChildRules()87 bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; }
setChildrenAffectedByFirstChildRules(bool value)88 void setChildrenAffectedByFirstChildRules(bool value) { m_childrenAffectedByFirstChildRules = value; }
childrenAffectedByLastChildRules()89 bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
setChildrenAffectedByLastChildRules(bool value)90 void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; }
childrenAffectedByDirectAdjacentRules()91 bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; }
setChildrenAffectedByDirectAdjacentRules(bool value)92 void setChildrenAffectedByDirectAdjacentRules(bool value) { m_childrenAffectedByDirectAdjacentRules = value; }
childrenAffectedByForwardPositionalRules()93 bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
setChildrenAffectedByForwardPositionalRules(bool value)94 void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; }
childrenAffectedByBackwardPositionalRules()95 bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
setChildrenAffectedByBackwardPositionalRules(bool value)96 void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; }
childIndex()97 unsigned childIndex() const { return m_childIndex; }
setChildIndex(unsigned index)98 void setChildIndex(unsigned index) { m_childIndex = index; }
99
clearShadow()100 void clearShadow() { m_shadow = nullptr; }
shadow()101 ElementShadow* shadow() const { return m_shadow.get(); }
ensureShadow()102 ElementShadow& ensureShadow()
103 {
104 if (!m_shadow)
105 m_shadow = ElementShadow::create();
106 return *m_shadow;
107 }
108
attributeMap()109 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
setAttributeMap(PassOwnPtr<NamedNodeMap> attributeMap)110 void setAttributeMap(PassOwnPtr<NamedNodeMap> attributeMap) { m_attributeMap = attributeMap; }
111
computedStyle()112 RenderStyle* computedStyle() const { return m_computedStyle.get(); }
setComputedStyle(PassRefPtr<RenderStyle> computedStyle)113 void setComputedStyle(PassRefPtr<RenderStyle> computedStyle) { m_computedStyle = computedStyle; }
clearComputedStyle()114 void clearComputedStyle() { m_computedStyle = 0; }
115
classList()116 ClassList* classList() const { return m_classList.get(); }
setClassList(PassOwnPtr<ClassList> classList)117 void setClassList(PassOwnPtr<ClassList> classList) { m_classList = classList; }
clearClassListValueForQuirksMode()118 void clearClassListValueForQuirksMode()
119 {
120 if (!m_classList)
121 return;
122 m_classList->clearValueForQuirksMode();
123 }
124
dataset()125 DatasetDOMStringMap* dataset() const { return m_dataset.get(); }
setDataset(PassOwnPtr<DatasetDOMStringMap> dataset)126 void setDataset(PassOwnPtr<DatasetDOMStringMap> dataset) { m_dataset = dataset; }
127
minimumSizeForResizing()128 LayoutSize minimumSizeForResizing() const { return m_minimumSizeForResizing; }
setMinimumSizeForResizing(LayoutSize size)129 void setMinimumSizeForResizing(LayoutSize size) { m_minimumSizeForResizing = size; }
130
savedLayerScrollOffset()131 IntSize savedLayerScrollOffset() const { return m_savedLayerScrollOffset; }
setSavedLayerScrollOffset(IntSize size)132 void setSavedLayerScrollOffset(IntSize size) { m_savedLayerScrollOffset = size; }
133
activeAnimations()134 ActiveAnimations* activeAnimations() { return m_activeAnimations.get(); }
setActiveAnimations(PassOwnPtr<ActiveAnimations> activeAnimations)135 void setActiveAnimations(PassOwnPtr<ActiveAnimations> activeAnimations)
136 {
137 m_activeAnimations = activeAnimations;
138 }
139
hasPendingResources()140 bool hasPendingResources() const { return m_hasPendingResources; }
setHasPendingResources(bool has)141 void setHasPendingResources(bool has) { m_hasPendingResources = has; }
142
hasInputMethodContext()143 bool hasInputMethodContext() const { return m_inputMethodContext; }
ensureInputMethodContext(HTMLElement * element)144 InputMethodContext* ensureInputMethodContext(HTMLElement* element)
145 {
146 if (!m_inputMethodContext)
147 m_inputMethodContext = InputMethodContext::create(element);
148 return m_inputMethodContext.get();
149 }
150
151 bool hasPseudoElements() const;
152
153 private:
154 short m_tabIndex;
155 unsigned short m_childIndex;
156 unsigned m_tabIndexWasSetExplicitly : 1;
157 unsigned m_needsFocusAppearanceUpdateSoonAfterAttach : 1;
158 unsigned m_styleAffectedByEmpty : 1;
159 unsigned m_isInCanvasSubtree : 1;
160 unsigned m_containsFullScreenElement : 1;
161 unsigned m_isInTopLayer : 1;
162 unsigned m_hasPendingResources : 1;
163 unsigned m_childrenAffectedByFocus : 1;
164 unsigned m_childrenAffectedByHover : 1;
165 unsigned m_childrenAffectedByActive : 1;
166 unsigned m_childrenAffectedByDrag : 1;
167 // Bits for dynamic child matching.
168 // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
169 // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
170 unsigned m_childrenAffectedByFirstChildRules : 1;
171 unsigned m_childrenAffectedByLastChildRules : 1;
172 unsigned m_childrenAffectedByDirectAdjacentRules : 1;
173 unsigned m_childrenAffectedByForwardPositionalRules : 1;
174 unsigned m_childrenAffectedByBackwardPositionalRules : 1;
175
176 unsigned m_isInsideRegion : 1;
177 RegionOversetState m_regionOversetState;
178
179 LayoutSize m_minimumSizeForResizing;
180 IntSize m_savedLayerScrollOffset;
181 RefPtr<RenderStyle> m_computedStyle;
182
183 OwnPtr<DatasetDOMStringMap> m_dataset;
184 OwnPtr<ClassList> m_classList;
185 OwnPtr<ElementShadow> m_shadow;
186 OwnPtr<NamedNodeMap> m_attributeMap;
187 OwnPtr<InputMethodContext> m_inputMethodContext;
188 OwnPtr<ActiveAnimations> m_activeAnimations;
189
190 RefPtr<PseudoElement> m_generatedBefore;
191 RefPtr<PseudoElement> m_generatedAfter;
192 RefPtr<PseudoElement> m_backdrop;
193
194 ElementRareData(RenderObject*);
195 };
196
defaultMinimumSizeForResizing()197 inline IntSize defaultMinimumSizeForResizing()
198 {
199 return IntSize(LayoutUnit::max(), LayoutUnit::max());
200 }
201
ElementRareData(RenderObject * renderer)202 inline ElementRareData::ElementRareData(RenderObject* renderer)
203 : NodeRareData(renderer)
204 , m_tabIndex(0)
205 , m_childIndex(0)
206 , m_tabIndexWasSetExplicitly(false)
207 , m_needsFocusAppearanceUpdateSoonAfterAttach(false)
208 , m_styleAffectedByEmpty(false)
209 , m_isInCanvasSubtree(false)
210 , m_containsFullScreenElement(false)
211 , m_isInTopLayer(false)
212 , m_hasPendingResources(false)
213 , m_childrenAffectedByFocus(false)
214 , m_childrenAffectedByHover(false)
215 , m_childrenAffectedByActive(false)
216 , m_childrenAffectedByDrag(false)
217 , m_childrenAffectedByFirstChildRules(false)
218 , m_childrenAffectedByLastChildRules(false)
219 , m_childrenAffectedByDirectAdjacentRules(false)
220 , m_childrenAffectedByForwardPositionalRules(false)
221 , m_childrenAffectedByBackwardPositionalRules(false)
222 , m_isInsideRegion(false)
223 , m_regionOversetState(RegionUndefined)
224 , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
225 {
226 }
227
~ElementRareData()228 inline ElementRareData::~ElementRareData()
229 {
230 ASSERT(!m_shadow);
231 ASSERT(!m_generatedBefore);
232 ASSERT(!m_generatedAfter);
233 ASSERT(!m_backdrop);
234 }
235
hasPseudoElements()236 inline bool ElementRareData::hasPseudoElements() const
237 {
238 return m_generatedBefore || m_generatedAfter || m_backdrop;
239 }
240
setPseudoElement(PseudoId pseudoId,PassRefPtr<PseudoElement> element)241 inline void ElementRareData::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element)
242 {
243 switch (pseudoId) {
244 case BEFORE:
245 if (m_generatedBefore)
246 m_generatedBefore->dispose();
247 m_generatedBefore = element;
248 break;
249 case AFTER:
250 if (m_generatedAfter)
251 m_generatedAfter->dispose();
252 m_generatedAfter = element;
253 break;
254 case BACKDROP:
255 if (m_backdrop)
256 m_backdrop->dispose();
257 m_backdrop = element;
258 break;
259 default:
260 ASSERT_NOT_REACHED();
261 }
262 }
263
pseudoElement(PseudoId pseudoId)264 inline PseudoElement* ElementRareData::pseudoElement(PseudoId pseudoId) const
265 {
266 switch (pseudoId) {
267 case BEFORE:
268 return m_generatedBefore.get();
269 case AFTER:
270 return m_generatedAfter.get();
271 case BACKDROP:
272 return m_backdrop.get();
273 default:
274 return 0;
275 }
276 }
277
resetStyleState()278 inline void ElementRareData::resetStyleState()
279 {
280 setStyleAffectedByEmpty(false);
281 setChildIndex(0);
282 }
283
resetDynamicRestyleObservations()284 inline void ElementRareData::resetDynamicRestyleObservations()
285 {
286 setChildrenAffectedByFocus(false);
287 setChildrenAffectedByHover(false);
288 setChildrenAffectedByActive(false);
289 setChildrenAffectedByDrag(false);
290 setChildrenAffectedByFirstChildRules(false);
291 setChildrenAffectedByLastChildRules(false);
292 setChildrenAffectedByDirectAdjacentRules(false);
293 setChildrenAffectedByForwardPositionalRules(false);
294 setChildrenAffectedByBackwardPositionalRules(false);
295 }
296
297 } // namespace
298
299 #endif // ElementRareData_h
300