diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderIterator.h')
-rw-r--r-- | Source/WebCore/rendering/RenderIterator.h | 120 |
1 files changed, 107 insertions, 13 deletions
diff --git a/Source/WebCore/rendering/RenderIterator.h b/Source/WebCore/rendering/RenderIterator.h index b50a344b9..ba172e72a 100644 --- a/Source/WebCore/rendering/RenderIterator.h +++ b/Source/WebCore/rendering/RenderIterator.h @@ -23,10 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RenderIterator_h -#define RenderIterator_h +#pragma once -#include "RenderObject.h" +#include "RenderElement.h" namespace WebCore { @@ -42,6 +41,7 @@ public: bool operator==(const RenderIterator& other) const; bool operator!=(const RenderIterator& other) const; + RenderIterator& traverseNext(); RenderIterator& traverseNextSibling(); RenderIterator& traversePreviousSibling(); RenderIterator& traverseAncestor(); @@ -63,6 +63,7 @@ public: bool operator==(const RenderConstIterator& other) const; bool operator!=(const RenderConstIterator& other) const; + RenderConstIterator& traverseNext(); RenderConstIterator& traverseNextSibling(); RenderConstIterator& traversePreviousSibling(); RenderConstIterator& traverseAncestor(); @@ -72,15 +73,76 @@ private: const T* m_current; }; +// Similar to WTF::is<>() but without the static_assert() making sure the check is necessary. +template <typename T, typename U> +inline bool isRendererOfType(const U& renderer) { return TypeCastTraits<const T, const U>::isOfType(renderer); } + // Traversal helpers +namespace RenderObjectTraversal { + +template <typename U> +inline RenderObject* firstChild(U& object) +{ + return object.firstChild(); +} + +inline RenderObject* firstChild(RenderObject& object) +{ + return object.firstChildSlow(); +} + +inline RenderObject* firstChild(RenderText&) +{ + return nullptr; +} + +inline RenderObject* nextAncestorSibling(RenderObject& current, const RenderObject* stayWithin) +{ + for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) { + if (ancestor == stayWithin) + return nullptr; + if (auto* sibling = ancestor->nextSibling()) + return sibling; + } + return nullptr; +} + +template <typename U> +inline RenderObject* next(U& current, const RenderObject* stayWithin) +{ + if (auto* child = firstChild(current)) + return child; + + if (¤t == stayWithin) + return nullptr; + + if (auto* sibling = current.nextSibling()) + return sibling; + + return nextAncestorSibling(current, stayWithin); +} + +inline RenderObject* nextSkippingChildren(RenderObject& current, const RenderObject* stayWithin) +{ + if (¤t == stayWithin) + return nullptr; + + if (auto* sibling = current.nextSibling()) + return sibling; + + return nextAncestorSibling(current, stayWithin); +} + +} + namespace RenderTraversal { template <typename T, typename U> inline T* firstChild(U& current) { - RenderObject* object = current.firstChild(); - while (object && !isRendererOfType<const T>(*object)) + RenderObject* object = RenderObjectTraversal::firstChild(current); + while (object && !isRendererOfType<T>(*object)) object = object->nextSibling(); return static_cast<T*>(object); } @@ -89,7 +151,7 @@ template <typename T, typename U> inline T* lastChild(U& current) { RenderObject* object = current.lastChild(); - while (object && !isRendererOfType<const T>(*object)) + while (object && !isRendererOfType<T>(*object)) object = object->previousSibling(); return static_cast<T*>(object); } @@ -98,7 +160,7 @@ template <typename T, typename U> inline T* nextSibling(U& current) { RenderObject* object = current.nextSibling(); - while (object && !isRendererOfType<const T>(*object)) + while (object && !isRendererOfType<T>(*object)) object = object->nextSibling(); return static_cast<T*>(object); } @@ -107,7 +169,7 @@ template <typename T, typename U> inline T* previousSibling(U& current) { RenderObject* object = current.previousSibling(); - while (object && !isRendererOfType<const T>(*object)) + while (object && !isRendererOfType<T>(*object)) object = object->previousSibling(); return static_cast<T*>(object); } @@ -115,13 +177,31 @@ inline T* previousSibling(U& current) template <typename T> inline T* findAncestorOfType(const RenderObject& current) { - for (auto ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) { - if (isRendererOfType<const T>(*ancestor)) + for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) { + if (isRendererOfType<T>(*ancestor)) return static_cast<T*>(ancestor); } return nullptr; } +template <typename T, typename U> +inline T* firstWithin(U& current) +{ + auto* descendant = RenderObjectTraversal::firstChild(current); + while (descendant && !isRendererOfType<T>(*descendant)) + descendant = RenderObjectTraversal::next(*descendant, ¤t); + return static_cast<T*>(descendant); +} + +template <typename T, typename U> +inline T* next(U& current, const RenderObject* stayWithin) +{ + auto* descendant = RenderObjectTraversal::next(current, stayWithin); + while (descendant && !isRendererOfType<T>(*descendant)) + descendant = RenderObjectTraversal::next(*descendant, stayWithin); + return static_cast<T*>(descendant); +} + } // namespace WebCore::RenderTraversal // RenderIterator @@ -149,6 +229,14 @@ inline RenderIterator<T>& RenderIterator<T>::traverseNextSibling() } template <typename T> +inline RenderIterator<T>& RenderIterator<T>::traverseNext() +{ + ASSERT(m_current); + m_current = RenderTraversal::next<T>(*m_current, m_root); + return *this; +} + +template <typename T> inline RenderIterator<T>& RenderIterator<T>::traversePreviousSibling() { ASSERT(m_current); @@ -217,6 +305,14 @@ inline RenderConstIterator<T>& RenderConstIterator<T>::traverseNextSibling() } template <typename T> +inline RenderConstIterator<T>& RenderConstIterator<T>::traverseNext() +{ + ASSERT(m_current); + m_current = RenderTraversal::next<T>(*m_current, m_root); + return *this; +} + +template <typename T> inline RenderConstIterator<T>& RenderConstIterator<T>::traversePreviousSibling() { ASSERT(m_current); @@ -261,9 +357,7 @@ inline bool RenderConstIterator<T>::operator!=(const RenderConstIterator& other) return !(*this == other); } -} +} // namespace WebCore #include "RenderAncestorIterator.h" #include "RenderChildIterator.h" - -#endif |