0a0c06f5da5239aa4cb144c673630849900ac2b9
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / NodeRenderingTraversal.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
13  *
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.
25  */
26
27 #include "config.h"
28 #include "core/dom/NodeRenderingTraversal.h"
29
30 #include "HTMLNames.h"
31 #include "core/dom/PseudoElement.h"
32 #include "core/dom/shadow/ComposedTreeWalker.h"
33 #include "core/rendering/RenderObject.h"
34
35 namespace WebCore {
36
37 namespace NodeRenderingTraversal {
38
39 static bool isRendererReparented(const RenderObject* renderer)
40 {
41     if (!renderer->node()->isElementNode())
42         return false;
43     if (toElement(renderer->node())->isInTopLayer())
44         return true;
45     return false;
46 }
47
48 void ParentDetails::didTraverseInsertionPoint(const InsertionPoint* insertionPoint)
49 {
50     if (!m_insertionPoint) {
51         m_insertionPoint = insertionPoint;
52     }
53 }
54
55 ContainerNode* parent(const Node* node, ParentDetails* details)
56 {
57     // FIXME: We should probably ASSERT(!node->document().childNeedsDistributionRecalc()) here, but
58     // a bunch of things use NodeRenderingTraversal::parent in places where that looks like it could
59     // be false.
60     ASSERT(node);
61     if (isActiveInsertionPoint(*node))
62         return 0;
63     ComposedTreeWalker walker(node, ComposedTreeWalker::CanStartFromShadowBoundary);
64     return toContainerNode(walker.traverseParent(walker.get(), details));
65 }
66
67 bool contains(const ContainerNode* container, const Node* node)
68 {
69     while (node) {
70         if (node == container)
71             return true;
72         node = NodeRenderingTraversal::parent(node);
73     }
74     return false;
75 }
76
77 Node* nextSibling(const Node* node)
78 {
79     ComposedTreeWalker walker(node);
80     if (node->isBeforePseudoElement()) {
81         walker.parent();
82         walker.firstChild();
83     } else
84         walker.nextSibling();
85
86     if (walker.get() || node->isAfterPseudoElement())
87         return walker.get();
88
89     Node* parent = walker.traverseParent(node);
90     if (parent && parent->isElementNode())
91         return toElement(parent)->pseudoElement(AFTER);
92
93     return 0;
94 }
95
96 Node* previousSibling(const Node* node)
97 {
98     ComposedTreeWalker walker(node);
99     if (node->isAfterPseudoElement()) {
100         walker.parent();
101         walker.lastChild();
102     } else
103         walker.previousSibling();
104
105     if (walker.get() || node->isBeforePseudoElement())
106         return walker.get();
107
108     Node* parent = walker.traverseParent(node);
109     if (parent && parent->isElementNode())
110         return toElement(parent)->pseudoElement(BEFORE);
111
112     return 0;
113 }
114
115 static Node* lastChild(const Node* node)
116 {
117     ComposedTreeWalker walker(node);
118     walker.lastChild();
119     return walker.get();
120 }
121
122 static Node* pseudoAwarePreviousSibling(const Node* node)
123 {
124     Node* previousNode = previousSibling(node);
125     Node* parentNode = parent(node);
126
127     if (parentNode && parentNode->isElementNode() && !previousNode) {
128         if (node->isAfterPseudoElement()) {
129             if (Node* child = lastChild(parentNode))
130                 return child;
131         }
132         if (!node->isBeforePseudoElement())
133             return toElement(parentNode)->pseudoElement(BEFORE);
134     }
135     return previousNode;
136 }
137
138 static Node* pseudoAwareLastChild(const Node* node)
139 {
140     if (node->isElementNode()) {
141         const Element* currentElement = toElement(node);
142         Node* last = currentElement->pseudoElement(AFTER);
143         if (last)
144             return last;
145
146         last = lastChild(currentElement);
147         if (!last)
148             last = currentElement->pseudoElement(BEFORE);
149         return last;
150     }
151
152     return lastChild(node);
153 }
154
155 Node* previous(const Node* node, const Node* stayWithin)
156 {
157     if (node == stayWithin)
158         return 0;
159
160     if (Node* previousNode = pseudoAwarePreviousSibling(node)) {
161         while (Node* previousLastChild = pseudoAwareLastChild(previousNode))
162             previousNode = previousLastChild;
163         return previousNode;
164     }
165     return parent(node);
166 }
167
168 static Node* firstChild(const Node* node)
169 {
170     ComposedTreeWalker walker(node);
171     walker.firstChild();
172     return walker.get();
173 }
174
175 static Node* pseudoAwareNextSibling(const Node* node)
176 {
177     Node* parentNode = parent(node);
178     Node* nextNode = nextSibling(node);
179
180     if (parentNode && parentNode->isElementNode() && !nextNode) {
181         if (node->isBeforePseudoElement()) {
182             if (Node* child = firstChild(parentNode))
183                 return child;
184         }
185         if (!node->isAfterPseudoElement())
186             return toElement(parentNode)->pseudoElement(AFTER);
187     }
188     return nextNode;
189 }
190
191 static Node* pseudoAwareFirstChild(const Node* node)
192 {
193     if (node->isElementNode()) {
194         const Element* currentElement = toElement(node);
195         Node* first = currentElement->pseudoElement(BEFORE);
196         if (first)
197             return first;
198         first = firstChild(currentElement);
199         if (!first)
200             first = currentElement->pseudoElement(AFTER);
201         return first;
202     }
203
204     return firstChild(node);
205 }
206
207 Node* next(const Node* node, const Node* stayWithin)
208 {
209     if (Node* child = pseudoAwareFirstChild(node))
210         return child;
211     if (node == stayWithin)
212         return 0;
213     if (Node* nextNode = pseudoAwareNextSibling(node))
214         return nextNode;
215     for (Node* parentNode = parent(node); parentNode; parentNode = parent(parentNode)) {
216         if (parentNode == stayWithin)
217             return 0;
218         if (Node* nextNode = pseudoAwareNextSibling(parentNode))
219             return nextNode;
220     }
221     return 0;
222 }
223
224 RenderObject* nextSiblingRenderer(const Node* node)
225 {
226     for (Node* sibling = NodeRenderingTraversal::nextSibling(node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
227         RenderObject* renderer = sibling->renderer();
228         if (renderer && !isRendererReparented(renderer))
229             return renderer;
230     }
231     return 0;
232 }
233
234 RenderObject* previousSiblingRenderer(const Node* node)
235 {
236     for (Node* sibling = NodeRenderingTraversal::previousSibling(node); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
237         RenderObject* renderer = sibling->renderer();
238         if (renderer && !isRendererReparented(renderer))
239             return renderer;
240     }
241     return 0;
242 }
243
244 RenderObject* nextInTopLayer(const Element* element)
245 {
246     if (!element->isInTopLayer())
247         return 0;
248     const WillBeHeapVector<RefPtrWillBeMember<Element> >& topLayerElements = element->document().topLayerElements();
249     size_t position = topLayerElements.find(element);
250     ASSERT(position != kNotFound);
251     for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
252         if (RenderObject* renderer = topLayerElements[i]->renderer())
253             return renderer;
254     }
255     return 0;
256 }
257
258 }
259
260 } // namespace