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 
     35 namespace WebCore {
     36 
     37 struct DOMSiblingTraversalStrategy {
     38     bool isFirstChild(Element*) const;
     39     bool isLastChild(Element*) const;
     40     bool isFirstOfType(Element*, const QualifiedName&) const;
     41     bool isLastOfType(Element*, const QualifiedName&) const;
     42 
     43     int countElementsBefore(Element*) const;
     44     int countElementsAfter(Element*) const;
     45     int countElementsOfTypeBefore(Element*, const QualifiedName&) const;
     46     int countElementsOfTypeAfter(Element*, const QualifiedName&) const;
     47 };
     48 
     49 inline bool DOMSiblingTraversalStrategy::isFirstChild(Element* element) const
     50 {
     51     return !element->previousElementSibling();
     52 }
     53 
     54 inline bool DOMSiblingTraversalStrategy::isLastChild(Element* element) const
     55 {
     56     return !element->nextElementSibling();
     57 }
     58 
     59 inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const
     60 {
     61     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     62         if (sibling->hasTagName(type))
     63             return false;
     64     }
     65     return true;
     66 }
     67 
     68 inline bool DOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const
     69 {
     70     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
     71         if (sibling->hasTagName(type))
     72             return false;
     73     }
     74     return true;
     75 }
     76 
     77 inline int DOMSiblingTraversalStrategy::countElementsBefore(Element* element) const
     78 {
     79     int count = 0;
     80     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling())
     81         count++;
     82 
     83     return count;
     84 }
     85 
     86 inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const
     87 {
     88     int count = 0;
     89     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     90         if (sibling->hasTagName(type))
     91             ++count;
     92     }
     93 
     94     return count;
     95 }
     96 
     97 inline int DOMSiblingTraversalStrategy::countElementsAfter(Element* element) const
     98 {
     99     int count = 0;
    100     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling())
    101         ++count;
    102 
    103     return count;
    104 }
    105 
    106 inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const
    107 {
    108     int count = 0;
    109     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
    110         if (sibling->hasTagName(type))
    111             ++count;
    112     }
    113 
    114     return count;
    115 }
    116 
    117 struct ShadowDOMSiblingTraversalStrategy {
    118     ShadowDOMSiblingTraversalStrategy(const Vector<Node*, 32>& siblings, int nth)
    119         : m_siblings(siblings)
    120         , m_nth(nth)
    121     {
    122     }
    123 
    124     bool isFirstChild(Element*) const;
    125     bool isLastChild(Element*) const;
    126     bool isFirstOfType(Element*, const QualifiedName&) const;
    127     bool isLastOfType(Element*, const QualifiedName&) const;
    128 
    129     int countElementsBefore(Element*) const;
    130     int countElementsAfter(Element*) const;
    131     int countElementsOfTypeBefore(Element*, const QualifiedName&) const;
    132     int countElementsOfTypeAfter(Element*, const QualifiedName&) const;
    133 
    134 private:
    135     const Vector<Node*, 32>& m_siblings;
    136     int m_nth;
    137 };
    138 
    139 inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element* element) const
    140 {
    141     ASSERT(element == toElement(m_siblings[m_nth]));
    142 
    143     for (int i = m_nth - 1; i >= 0; --i) {
    144         if (m_siblings[i]->isElementNode())
    145             return false;
    146     }
    147 
    148     return true;
    149 }
    150 
    151 inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element* element) const
    152 {
    153     ASSERT(element == toElement(m_siblings[m_nth]));
    154 
    155     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    156         if (m_siblings[i]->isElementNode())
    157             return false;
    158     }
    159 
    160     return true;
    161 }
    162 
    163 inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const
    164 {
    165     ASSERT(element == toElement(m_siblings[m_nth]));
    166 
    167     for (int i = m_nth - 1; i >= 0; --i) {
    168         if (m_siblings[i]->hasTagName(type))
    169             return false;
    170     }
    171 
    172     return true;
    173 }
    174 
    175 inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const
    176 {
    177     ASSERT(element == toElement(m_siblings[m_nth]));
    178 
    179     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    180         if (m_siblings[i]->hasTagName(type))
    181             return false;
    182     }
    183 
    184     return true;
    185 }
    186 
    187 inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element* element) const
    188 {
    189     ASSERT(element == toElement(m_siblings[m_nth]));
    190 
    191     int count = 0;
    192     for (int i = m_nth - 1; i >= 0; --i) {
    193         if (m_siblings[i]->isElementNode())
    194             ++count;
    195     }
    196 
    197     return count;
    198 }
    199 
    200 inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element* element) const
    201 {
    202     ASSERT(element == toElement(m_siblings[m_nth]));
    203 
    204     int count = 0;
    205     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    206         if (m_siblings[i]->isElementNode())
    207             return ++count;
    208     }
    209 
    210     return count;
    211 }
    212 
    213 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const
    214 {
    215     ASSERT(element == toElement(m_siblings[m_nth]));
    216 
    217     int count = 0;
    218     for (int i = m_nth - 1; i >= 0; --i) {
    219         if (m_siblings[i]->hasTagName(type))
    220             ++count;
    221     }
    222 
    223     return count;
    224 }
    225 
    226 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const
    227 {
    228     ASSERT(element == toElement(m_siblings[m_nth]));
    229 
    230     int count = 0;
    231     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    232         if (m_siblings[i]->hasTagName(type))
    233             return ++count;
    234     }
    235 
    236     return count;
    237 }
    238 
    239 }
    240 
    241 #endif
    242