2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Neither the name of Google Inc. nor the names of its
11 * contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "core/dom/NodeRenderingTraversal.h"
30 #include "core/HTMLNames.h"
31 #include "core/dom/PseudoElement.h"
32 #include "core/dom/shadow/ComposedTreeWalker.h"
33 #include "core/rendering/RenderObject.h"
37 namespace NodeRenderingTraversal {
39 static bool isRendererReparented(const RenderObject* renderer)
41 if (!renderer->node()->isElementNode())
43 if (toElement(renderer->node())->isInTopLayer())
48 void ParentDetails::didTraverseInsertionPoint(const InsertionPoint* insertionPoint)
50 if (!m_insertionPoint) {
51 m_insertionPoint = insertionPoint;
55 ContainerNode* parent(const Node* node, ParentDetails* details)
58 ASSERT(!node->document().childNeedsDistributionRecalc());
59 if (isActiveInsertionPoint(*node))
61 ComposedTreeWalker walker(node, ComposedTreeWalker::CanStartFromShadowBoundary);
62 return toContainerNode(walker.traverseParent(walker.get(), details));
65 bool contains(const ContainerNode* container, const Node* node)
68 if (node == container)
70 node = NodeRenderingTraversal::parent(node);
75 Node* nextSibling(const Node* node)
77 ComposedTreeWalker walker(node);
78 if (node->isBeforePseudoElement()) {
84 if (walker.get() || node->isAfterPseudoElement())
87 Node* parent = walker.traverseParent(node);
88 if (parent && parent->isElementNode())
89 return toElement(parent)->pseudoElement(AFTER);
94 Node* previousSibling(const Node* node)
96 ComposedTreeWalker walker(node);
97 if (node->isAfterPseudoElement()) {
101 walker.previousSibling();
103 if (walker.get() || node->isBeforePseudoElement())
106 Node* parent = walker.traverseParent(node);
107 if (parent && parent->isElementNode())
108 return toElement(parent)->pseudoElement(BEFORE);
113 static Node* lastChild(const Node* node)
115 ComposedTreeWalker walker(node);
120 static Node* pseudoAwarePreviousSibling(const Node* node)
122 Node* previousNode = previousSibling(node);
123 Node* parentNode = parent(node);
125 if (parentNode && parentNode->isElementNode() && !previousNode) {
126 if (node->isAfterPseudoElement()) {
127 if (Node* child = lastChild(parentNode))
130 if (!node->isBeforePseudoElement())
131 return toElement(parentNode)->pseudoElement(BEFORE);
136 static Node* pseudoAwareLastChild(const Node* node)
138 if (node->isElementNode()) {
139 const Element* currentElement = toElement(node);
140 Node* last = currentElement->pseudoElement(AFTER);
144 last = lastChild(currentElement);
146 last = currentElement->pseudoElement(BEFORE);
150 return lastChild(node);
153 Node* previous(const Node* node, const Node* stayWithin)
155 if (node == stayWithin)
158 if (Node* previousNode = pseudoAwarePreviousSibling(node)) {
159 while (Node* previousLastChild = pseudoAwareLastChild(previousNode))
160 previousNode = previousLastChild;
166 Node* firstChild(const Node* node)
168 ComposedTreeWalker walker(node);
173 static Node* pseudoAwareNextSibling(const Node* node)
175 Node* parentNode = parent(node);
176 Node* nextNode = nextSibling(node);
178 if (parentNode && parentNode->isElementNode() && !nextNode) {
179 if (node->isBeforePseudoElement()) {
180 if (Node* child = firstChild(parentNode))
183 if (!node->isAfterPseudoElement())
184 return toElement(parentNode)->pseudoElement(AFTER);
189 static Node* pseudoAwareFirstChild(const Node* node)
191 if (node->isElementNode()) {
192 const Element* currentElement = toElement(node);
193 Node* first = currentElement->pseudoElement(BEFORE);
196 first = firstChild(currentElement);
198 first = currentElement->pseudoElement(AFTER);
202 return firstChild(node);
205 Node* next(const Node* node, const Node* stayWithin)
207 if (Node* child = pseudoAwareFirstChild(node))
209 if (node == stayWithin)
211 if (Node* nextNode = pseudoAwareNextSibling(node))
213 for (Node* parentNode = parent(node); parentNode; parentNode = parent(parentNode)) {
214 if (parentNode == stayWithin)
216 if (Node* nextNode = pseudoAwareNextSibling(parentNode))
222 RenderObject* nextSiblingRenderer(const Node* node)
224 for (Node* sibling = NodeRenderingTraversal::nextSibling(node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
225 RenderObject* renderer = sibling->renderer();
226 if (renderer && !isRendererReparented(renderer))
232 RenderObject* previousSiblingRenderer(const Node* node)
234 for (Node* sibling = NodeRenderingTraversal::previousSibling(node); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
235 RenderObject* renderer = sibling->renderer();
236 if (renderer && !isRendererReparented(renderer))
242 RenderObject* nextInTopLayer(const Element* element)
244 if (!element->isInTopLayer())
246 const WillBeHeapVector<RefPtrWillBeMember<Element> >& topLayerElements = element->document().topLayerElements();
247 size_t position = topLayerElements.find(element);
248 ASSERT(position != kNotFound);
249 for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
250 if (RenderObject* renderer = topLayerElements[i]->renderer())