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 childrenAffectedByHover() const { return m_childrenAffectedByHover; } 79 void setChildrenAffectedByHover(bool value) { m_childrenAffectedByHover = value; } 80 bool childrenAffectedByActive() const { return m_childrenAffectedByActive; } 81 void setChildrenAffectedByActive(bool value) { m_childrenAffectedByActive = value; } 82 bool childrenAffectedByDrag() const { return m_childrenAffectedByDrag; } 83 void setChildrenAffectedByDrag(bool value) { m_childrenAffectedByDrag = value; } 84 85 bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; } 86 void setChildrenAffectedByFirstChildRules(bool value) { m_childrenAffectedByFirstChildRules = value; } 87 bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; } 88 void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; } 89 bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; } 90 void setChildrenAffectedByDirectAdjacentRules(bool value) { m_childrenAffectedByDirectAdjacentRules = value; } 91 bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; } 92 void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; } 93 bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; } 94 void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; } 95 unsigned childIndex() const { return m_childIndex; } 96 void setChildIndex(unsigned index) { m_childIndex = index; } 97 98 void clearShadow() { m_shadow = nullptr; } 99 ElementShadow* shadow() const { return m_shadow.get(); } 100 ElementShadow* ensureShadow() 101 { 102 if (!m_shadow) 103 m_shadow = ElementShadow::create(); 104 return m_shadow.get(); 105 } 106 107 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); } 108 void setAttributeMap(PassOwnPtr<NamedNodeMap> attributeMap) { m_attributeMap = attributeMap; } 109 110 RenderStyle* computedStyle() const { return m_computedStyle.get(); } 111 void setComputedStyle(PassRefPtr<RenderStyle> computedStyle) { m_computedStyle = computedStyle; } 112 void clearComputedStyle() { m_computedStyle = 0; } 113 114 ClassList* classList() const { return m_classList.get(); } 115 void setClassList(PassOwnPtr<ClassList> classList) { m_classList = classList; } 116 void clearClassListValueForQuirksMode() 117 { 118 if (!m_classList) 119 return; 120 m_classList->clearValueForQuirksMode(); 121 } 122 123 DatasetDOMStringMap* dataset() const { return m_dataset.get(); } 124 void setDataset(PassOwnPtr<DatasetDOMStringMap> dataset) { m_dataset = dataset; } 125 126 LayoutSize minimumSizeForResizing() const { return m_minimumSizeForResizing; } 127 void setMinimumSizeForResizing(LayoutSize size) { m_minimumSizeForResizing = size; } 128 129 IntSize savedLayerScrollOffset() const { return m_savedLayerScrollOffset; } 130 void setSavedLayerScrollOffset(IntSize size) { m_savedLayerScrollOffset = size; } 131 132 ActiveAnimations* activeAnimations() { return m_activeAnimations.get(); } 133 void setActiveAnimations(PassOwnPtr<ActiveAnimations> activeAnimations) 134 { 135 m_activeAnimations = activeAnimations; 136 } 137 138 bool hasPendingResources() const { return m_hasPendingResources; } 139 void setHasPendingResources(bool has) { m_hasPendingResources = has; } 140 141 InputMethodContext* ensureInputMethodContext(HTMLElement* element) 142 { 143 if (!m_inputMethodContext) 144 m_inputMethodContext = InputMethodContext::create(element); 145 return m_inputMethodContext.get(); 146 } 147 148 private: 149 short m_tabIndex; 150 unsigned short m_childIndex; 151 unsigned m_tabIndexWasSetExplicitly : 1; 152 unsigned m_needsFocusAppearanceUpdateSoonAfterAttach : 1; 153 unsigned m_styleAffectedByEmpty : 1; 154 unsigned m_isInCanvasSubtree : 1; 155 unsigned m_containsFullScreenElement : 1; 156 unsigned m_isInTopLayer : 1; 157 unsigned m_hasPendingResources : 1; 158 unsigned m_childrenAffectedByHover : 1; 159 unsigned m_childrenAffectedByActive : 1; 160 unsigned m_childrenAffectedByDrag : 1; 161 // Bits for dynamic child matching. 162 // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or 163 // *-child-of-type, we will just give up and re-evaluate whenever children change at all. 164 unsigned m_childrenAffectedByFirstChildRules : 1; 165 unsigned m_childrenAffectedByLastChildRules : 1; 166 unsigned m_childrenAffectedByDirectAdjacentRules : 1; 167 unsigned m_childrenAffectedByForwardPositionalRules : 1; 168 unsigned m_childrenAffectedByBackwardPositionalRules : 1; 169 170 unsigned m_isInsideRegion : 1; 171 RegionOversetState m_regionOversetState; 172 173 LayoutSize m_minimumSizeForResizing; 174 IntSize m_savedLayerScrollOffset; 175 RefPtr<RenderStyle> m_computedStyle; 176 177 OwnPtr<DatasetDOMStringMap> m_dataset; 178 OwnPtr<ClassList> m_classList; 179 OwnPtr<ElementShadow> m_shadow; 180 OwnPtr<NamedNodeMap> m_attributeMap; 181 OwnPtr<InputMethodContext> m_inputMethodContext; 182 OwnPtr<ActiveAnimations> m_activeAnimations; 183 184 RefPtr<PseudoElement> m_generatedBefore; 185 RefPtr<PseudoElement> m_generatedAfter; 186 RefPtr<PseudoElement> m_backdrop; 187 188 ElementRareData(RenderObject*); 189 void releasePseudoElement(PseudoElement*); 190 }; 191 192 inline IntSize defaultMinimumSizeForResizing() 193 { 194 return IntSize(LayoutUnit::max(), LayoutUnit::max()); 195 } 196 197 inline ElementRareData::ElementRareData(RenderObject* renderer) 198 : NodeRareData(renderer) 199 , m_tabIndex(0) 200 , m_childIndex(0) 201 , m_tabIndexWasSetExplicitly(false) 202 , m_needsFocusAppearanceUpdateSoonAfterAttach(false) 203 , m_styleAffectedByEmpty(false) 204 , m_isInCanvasSubtree(false) 205 , m_containsFullScreenElement(false) 206 , m_isInTopLayer(false) 207 , m_hasPendingResources(false) 208 , m_childrenAffectedByHover(false) 209 , m_childrenAffectedByActive(false) 210 , m_childrenAffectedByDrag(false) 211 , m_childrenAffectedByFirstChildRules(false) 212 , m_childrenAffectedByLastChildRules(false) 213 , m_childrenAffectedByDirectAdjacentRules(false) 214 , m_childrenAffectedByForwardPositionalRules(false) 215 , m_childrenAffectedByBackwardPositionalRules(false) 216 , m_isInsideRegion(false) 217 , m_regionOversetState(RegionUndefined) 218 , m_minimumSizeForResizing(defaultMinimumSizeForResizing()) 219 { 220 } 221 222 inline ElementRareData::~ElementRareData() 223 { 224 ASSERT(!m_shadow); 225 ASSERT(!m_generatedBefore); 226 ASSERT(!m_generatedAfter); 227 ASSERT(!m_backdrop); 228 } 229 230 inline void ElementRareData::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element) 231 { 232 switch (pseudoId) { 233 case BEFORE: 234 releasePseudoElement(m_generatedBefore.get()); 235 m_generatedBefore = element; 236 break; 237 case AFTER: 238 releasePseudoElement(m_generatedAfter.get()); 239 m_generatedAfter = element; 240 break; 241 case BACKDROP: 242 releasePseudoElement(m_backdrop.get()); 243 m_backdrop = element; 244 break; 245 default: 246 ASSERT_NOT_REACHED(); 247 } 248 } 249 250 inline PseudoElement* ElementRareData::pseudoElement(PseudoId pseudoId) const 251 { 252 switch (pseudoId) { 253 case BEFORE: 254 return m_generatedBefore.get(); 255 case AFTER: 256 return m_generatedAfter.get(); 257 case BACKDROP: 258 return m_backdrop.get(); 259 default: 260 return 0; 261 } 262 } 263 264 inline void ElementRareData::releasePseudoElement(PseudoElement* element) 265 { 266 if (!element) 267 return; 268 269 if (element->attached()) 270 element->detach(); 271 272 ASSERT(!element->nextSibling()); 273 ASSERT(!element->previousSibling()); 274 275 element->document()->removeFromTopLayer(element); 276 element->setParentOrShadowHostNode(0); 277 } 278 279 inline void ElementRareData::resetStyleState() 280 { 281 setComputedStyle(0); 282 setStyleAffectedByEmpty(false); 283 setChildIndex(0); 284 } 285 286 inline void ElementRareData::resetDynamicRestyleObservations() 287 { 288 setChildrenAffectedByHover(false); 289 setChildrenAffectedByActive(false); 290 setChildrenAffectedByDrag(false); 291 setChildrenAffectedByFirstChildRules(false); 292 setChildrenAffectedByLastChildRules(false); 293 setChildrenAffectedByDirectAdjacentRules(false); 294 setChildrenAffectedByForwardPositionalRules(false); 295 setChildrenAffectedByBackwardPositionalRules(false); 296 } 297 298 } // namespace 299 300 #endif // ElementRareData_h 301