Home | History | Annotate | Download | only in dom
      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