1 /* 2 * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 David Smith <catfish.man (at) 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: 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 52 short tabIndex() const { return m_tabIndex; } 53 void setTabIndexExplicitly(short index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; } 54 bool tabIndexSetExplicitly() const { return m_tabIndexWasSetExplicitly; } 55 void clearTabIndexExplicitly() { m_tabIndex = 0; m_tabIndexWasSetExplicitly = false; } 56 57 bool needsFocusAppearanceUpdateSoonAfterAttach() const { return m_needsFocusAppearanceUpdateSoonAfterAttach; } 58 void setNeedsFocusAppearanceUpdateSoonAfterAttach(bool needs) { m_needsFocusAppearanceUpdateSoonAfterAttach = needs; } 59 60 bool styleAffectedByEmpty() const { return m_styleAffectedByEmpty; } 61 void setStyleAffectedByEmpty(bool value) { m_styleAffectedByEmpty = value; } 62 63 bool isInCanvasSubtree() const { return m_isInCanvasSubtree; } 64 void setIsInCanvasSubtree(bool value) { m_isInCanvasSubtree = value; } 65 66 bool isInsideRegion() const { return m_isInsideRegion; } 67 void setIsInsideRegion(bool value) { m_isInsideRegion = value; } 68 69 RegionOversetState regionOversetState() const { return m_regionOversetState; } 70 void setRegionOversetState(RegionOversetState state) { m_regionOversetState = state; } 71 72 bool containsFullScreenElement() { return m_containsFullScreenElement; } 73 void setContainsFullScreenElement(bool value) { m_containsFullScreenElement = value; } 74 75 bool isInTopLayer() const { return m_isInTopLayer; } 76 void setIsInTopLayer(bool value) { m_isInTopLayer = value; } 77 78 bool childrenAffectedByFocus() const { return m_childrenAffectedByFocus; } 79 void setChildrenAffectedByFocus(bool value) { m_childrenAffectedByFocus = value; } 80 bool childrenAffectedByHover() const { return m_childrenAffectedByHover; } 81 void setChildrenAffectedByHover(bool value) { m_childrenAffectedByHover = value; } 82 bool childrenAffectedByActive() const { return m_childrenAffectedByActive; } 83 void setChildrenAffectedByActive(bool value) { m_childrenAffectedByActive = value; } 84 bool childrenAffectedByDrag() const { return m_childrenAffectedByDrag; } 85 void setChildrenAffectedByDrag(bool value) { m_childrenAffectedByDrag = value; } 86 87 bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; } 88 void setChildrenAffectedByFirstChildRules(bool value) { m_childrenAffectedByFirstChildRules = value; } 89 bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; } 90 void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; } 91 bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; } 92 void setChildrenAffectedByDirectAdjacentRules(bool value) { m_childrenAffectedByDirectAdjacentRules = value; } 93 bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; } 94 void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; } 95 bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; } 96 void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; } 97 unsigned childIndex() const { return m_childIndex; } 98 void setChildIndex(unsigned index) { m_childIndex = index; } 99 100 void clearShadow() { m_shadow = nullptr; } 101 ElementShadow* shadow() const { return m_shadow.get(); } 102 ElementShadow& ensureShadow() 103 { 104 if (!m_shadow) 105 m_shadow = ElementShadow::create(); 106 return *m_shadow; 107 } 108 109 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); } 110 void setAttributeMap(PassOwnPtr<NamedNodeMap> attributeMap) { m_attributeMap = attributeMap; } 111 112 RenderStyle* computedStyle() const { return m_computedStyle.get(); } 113 void setComputedStyle(PassRefPtr<RenderStyle> computedStyle) { m_computedStyle = computedStyle; } 114 void clearComputedStyle() { m_computedStyle = 0; } 115 116 ClassList* classList() const { return m_classList.get(); } 117 void setClassList(PassOwnPtr<ClassList> classList) { m_classList = classList; } 118 void clearClassListValueForQuirksMode() 119 { 120 if (!m_classList) 121 return; 122 m_classList->clearValueForQuirksMode(); 123 } 124 125 DatasetDOMStringMap* dataset() const { return m_dataset.get(); } 126 void setDataset(PassOwnPtr<DatasetDOMStringMap> dataset) { m_dataset = dataset; } 127 128 LayoutSize minimumSizeForResizing() const { return m_minimumSizeForResizing; } 129 void setMinimumSizeForResizing(LayoutSize size) { m_minimumSizeForResizing = size; } 130 131 IntSize savedLayerScrollOffset() const { return m_savedLayerScrollOffset; } 132 void setSavedLayerScrollOffset(IntSize size) { m_savedLayerScrollOffset = size; } 133 134 ActiveAnimations* activeAnimations() { return m_activeAnimations.get(); } 135 void setActiveAnimations(PassOwnPtr<ActiveAnimations> activeAnimations) 136 { 137 m_activeAnimations = activeAnimations; 138 } 139 140 bool hasPendingResources() const { return m_hasPendingResources; } 141 void setHasPendingResources(bool has) { m_hasPendingResources = has; } 142 143 bool hasInputMethodContext() const { return m_inputMethodContext; } 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 197 inline IntSize defaultMinimumSizeForResizing() 198 { 199 return IntSize(LayoutUnit::max(), LayoutUnit::max()); 200 } 201 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 228 inline ElementRareData::~ElementRareData() 229 { 230 ASSERT(!m_shadow); 231 ASSERT(!m_generatedBefore); 232 ASSERT(!m_generatedAfter); 233 ASSERT(!m_backdrop); 234 } 235 236 inline bool ElementRareData::hasPseudoElements() const 237 { 238 return m_generatedBefore || m_generatedAfter || m_backdrop; 239 } 240 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 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 278 inline void ElementRareData::resetStyleState() 279 { 280 setStyleAffectedByEmpty(false); 281 setChildIndex(0); 282 } 283 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