Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      7  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
     11  * Copyright (C) 2012, Google, Inc. All rights reserved.
     12  *
     13  * This library is free software; you can redistribute it and/or
     14  * modify it under the terms of the GNU Library General Public
     15  * License as published by the Free Software Foundation; either
     16  * version 2 of the License, or (at your option) any later version.
     17  *
     18  * This library is distributed in the hope that it will be useful,
     19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21  * Library General Public License for more details.
     22  *
     23  * You should have received a copy of the GNU Library General Public License
     24  * along with this library; see the file COPYING.LIB.  If not, write to
     25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     26  * Boston, MA 02110-1301, USA.
     27  */
     28 
     29 #ifndef SiblingTraversalStrategies_h
     30 #define SiblingTraversalStrategies_h
     31 
     32 #include "core/dom/Element.h"
     33 #include "core/rendering/style/RenderStyle.h"
     34 #include "wtf/UnusedParam.h"
     35 
     36 namespace WebCore {
     37 
     38 struct DOMSiblingTraversalStrategy {
     39     bool isFirstChild(Element*) const;
     40     bool isLastChild(Element*) const;
     41     bool isFirstOfType(Element*, const QualifiedName&) const;
     42     bool isLastOfType(Element*, const QualifiedName&) const;
     43 
     44     int countElementsBefore(Element*) const;
     45     int countElementsAfter(Element*) const;
     46     int countElementsOfTypeBefore(Element*, const QualifiedName&) const;
     47     int countElementsOfTypeAfter(Element*, const QualifiedName&) const;
     48 };
     49 
     50 inline bool DOMSiblingTraversalStrategy::isFirstChild(Element* element) const
     51 {
     52     return !element->previousElementSibling();
     53 }
     54 
     55 inline bool DOMSiblingTraversalStrategy::isLastChild(Element* element) const
     56 {
     57     return !element->nextElementSibling();
     58 }
     59 
     60 inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const
     61 {
     62     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     63         if (sibling->hasTagName(type))
     64             return false;
     65     }
     66     return true;
     67 }
     68 
     69 inline bool DOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const
     70 {
     71     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
     72         if (sibling->hasTagName(type))
     73             return false;
     74     }
     75     return true;
     76 }
     77 
     78 inline int DOMSiblingTraversalStrategy::countElementsBefore(Element* element) const
     79 {
     80     int count = 0;
     81     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     82         unsigned index = sibling->childIndex();
     83         if (index) {
     84             count += index;
     85             break;
     86         }
     87         count++;
     88     }
     89 
     90     return count;
     91 }
     92 
     93 inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const
     94 {
     95     int count = 0;
     96     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     97         if (sibling->hasTagName(type))
     98             ++count;
     99     }
    100 
    101     return count;
    102 }
    103 
    104 inline int DOMSiblingTraversalStrategy::countElementsAfter(Element* element) const
    105 {
    106     int count = 0;
    107     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling())
    108         ++count;
    109 
    110     return count;
    111 }
    112 
    113 inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const
    114 {
    115     int count = 0;
    116     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
    117         if (sibling->hasTagName(type))
    118             ++count;
    119     }
    120 
    121     return count;
    122 }
    123 
    124 struct ShadowDOMSiblingTraversalStrategy {
    125     ShadowDOMSiblingTraversalStrategy(const Vector<Node*>& siblings, int nth)
    126         : m_siblings(siblings)
    127         , m_nth(nth)
    128     {
    129     }
    130 
    131     bool isFirstChild(Element*) const;
    132     bool isLastChild(Element*) const;
    133     bool isFirstOfType(Element*, const QualifiedName&) const;
    134     bool isLastOfType(Element*, const QualifiedName&) const;
    135 
    136     int countElementsBefore(Element*) const;
    137     int countElementsAfter(Element*) const;
    138     int countElementsOfTypeBefore(Element*, const QualifiedName&) const;
    139     int countElementsOfTypeAfter(Element*, const QualifiedName&) const;
    140 
    141 private:
    142     Vector<Node*> m_siblings;
    143     int m_nth;
    144 };
    145 
    146 inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element* element) const
    147 {
    148     UNUSED_PARAM(element);
    149 
    150     ASSERT(element == toElement(m_siblings[m_nth]));
    151 
    152     for (int i = m_nth - 1; i >= 0; --i) {
    153         if (m_siblings[i]->isElementNode())
    154             return false;
    155     }
    156 
    157     return true;
    158 }
    159 
    160 inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element* element) const
    161 {
    162     UNUSED_PARAM(element);
    163 
    164     ASSERT(element == toElement(m_siblings[m_nth]));
    165 
    166     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    167         if (m_siblings[i]->isElementNode())
    168             return false;
    169     }
    170 
    171     return true;
    172 }
    173 
    174 inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const
    175 {
    176     UNUSED_PARAM(element);
    177 
    178     ASSERT(element == toElement(m_siblings[m_nth]));
    179 
    180     for (int i = m_nth - 1; i >= 0; --i) {
    181         if (m_siblings[i]->hasTagName(type))
    182             return false;
    183     }
    184 
    185     return true;
    186 }
    187 
    188 inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const
    189 {
    190     UNUSED_PARAM(element);
    191 
    192     ASSERT(element == toElement(m_siblings[m_nth]));
    193 
    194     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    195         if (m_siblings[i]->hasTagName(type))
    196             return false;
    197     }
    198 
    199     return true;
    200 }
    201 
    202 inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element* element) const
    203 {
    204     UNUSED_PARAM(element);
    205 
    206     ASSERT(element == toElement(m_siblings[m_nth]));
    207 
    208     int count = 0;
    209     for (int i = m_nth - 1; i >= 0; --i) {
    210         if (m_siblings[i]->isElementNode())
    211             ++count;
    212     }
    213 
    214     return count;
    215 }
    216 
    217 inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element* element) const
    218 {
    219     UNUSED_PARAM(element);
    220 
    221     ASSERT(element == toElement(m_siblings[m_nth]));
    222 
    223     int count = 0;
    224     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    225         if (m_siblings[i]->isElementNode())
    226             return ++count;
    227     }
    228 
    229     return count;
    230 }
    231 
    232 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const
    233 {
    234     UNUSED_PARAM(element);
    235 
    236     ASSERT(element == toElement(m_siblings[m_nth]));
    237 
    238     int count = 0;
    239     for (int i = m_nth - 1; i >= 0; --i) {
    240         if (m_siblings[i]->hasTagName(type))
    241             ++count;
    242     }
    243 
    244     return count;
    245 }
    246 
    247 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const
    248 {
    249     UNUSED_PARAM(element);
    250 
    251     ASSERT(element == toElement(m_siblings[m_nth]));
    252 
    253     int count = 0;
    254     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    255         if (m_siblings[i]->hasTagName(type))
    256             return ++count;
    257     }
    258 
    259     return count;
    260 }
    261 
    262 }
    263 
    264 #endif
    265