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 "core/HTMLNames.h" 31#include "core/dom/PseudoElement.h" 32#include "core/dom/shadow/ComposedTreeWalker.h" 33#include "core/rendering/RenderObject.h" 34 35namespace blink { 36 37namespace NodeRenderingTraversal { 38 39static 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 48void ParentDetails::didTraverseInsertionPoint(const InsertionPoint* insertionPoint) 49{ 50 if (!m_insertionPoint) { 51 m_insertionPoint = insertionPoint; 52 } 53} 54 55ContainerNode* parent(const Node* node, ParentDetails* details) 56{ 57 ASSERT(node); 58 ASSERT(!node->document().childNeedsDistributionRecalc()); 59 if (isActiveInsertionPoint(*node)) 60 return 0; 61 ComposedTreeWalker walker(node, ComposedTreeWalker::CanStartFromShadowBoundary); 62 return toContainerNode(walker.traverseParent(walker.get(), details)); 63} 64 65bool contains(const ContainerNode* container, const Node* node) 66{ 67 while (node) { 68 if (node == container) 69 return true; 70 node = NodeRenderingTraversal::parent(node); 71 } 72 return false; 73} 74 75Node* nextSibling(const Node* node) 76{ 77 ComposedTreeWalker walker(node); 78 if (node->isBeforePseudoElement()) { 79 walker.parent(); 80 walker.firstChild(); 81 } else 82 walker.nextSibling(); 83 84 if (walker.get() || node->isAfterPseudoElement()) 85 return walker.get(); 86 87 Node* parent = walker.traverseParent(node); 88 if (parent && parent->isElementNode()) 89 return toElement(parent)->pseudoElement(AFTER); 90 91 return 0; 92} 93 94Node* previousSibling(const Node* node) 95{ 96 ComposedTreeWalker walker(node); 97 if (node->isAfterPseudoElement()) { 98 walker.parent(); 99 walker.lastChild(); 100 } else 101 walker.previousSibling(); 102 103 if (walker.get() || node->isBeforePseudoElement()) 104 return walker.get(); 105 106 Node* parent = walker.traverseParent(node); 107 if (parent && parent->isElementNode()) 108 return toElement(parent)->pseudoElement(BEFORE); 109 110 return 0; 111} 112 113static Node* lastChild(const Node* node) 114{ 115 ComposedTreeWalker walker(node); 116 walker.lastChild(); 117 return walker.get(); 118} 119 120static Node* pseudoAwarePreviousSibling(const Node* node) 121{ 122 Node* previousNode = previousSibling(node); 123 Node* parentNode = parent(node); 124 125 if (parentNode && parentNode->isElementNode() && !previousNode) { 126 if (node->isAfterPseudoElement()) { 127 if (Node* child = lastChild(parentNode)) 128 return child; 129 } 130 if (!node->isBeforePseudoElement()) 131 return toElement(parentNode)->pseudoElement(BEFORE); 132 } 133 return previousNode; 134} 135 136static Node* pseudoAwareLastChild(const Node* node) 137{ 138 if (node->isElementNode()) { 139 const Element* currentElement = toElement(node); 140 Node* last = currentElement->pseudoElement(AFTER); 141 if (last) 142 return last; 143 144 last = lastChild(currentElement); 145 if (!last) 146 last = currentElement->pseudoElement(BEFORE); 147 return last; 148 } 149 150 return lastChild(node); 151} 152 153Node* previous(const Node* node, const Node* stayWithin) 154{ 155 if (node == stayWithin) 156 return 0; 157 158 if (Node* previousNode = pseudoAwarePreviousSibling(node)) { 159 while (Node* previousLastChild = pseudoAwareLastChild(previousNode)) 160 previousNode = previousLastChild; 161 return previousNode; 162 } 163 return parent(node); 164} 165 166static Node* firstChild(const Node* node) 167{ 168 ComposedTreeWalker walker(node); 169 walker.firstChild(); 170 return walker.get(); 171} 172 173static Node* pseudoAwareNextSibling(const Node* node) 174{ 175 Node* parentNode = parent(node); 176 Node* nextNode = nextSibling(node); 177 178 if (parentNode && parentNode->isElementNode() && !nextNode) { 179 if (node->isBeforePseudoElement()) { 180 if (Node* child = firstChild(parentNode)) 181 return child; 182 } 183 if (!node->isAfterPseudoElement()) 184 return toElement(parentNode)->pseudoElement(AFTER); 185 } 186 return nextNode; 187} 188 189static Node* pseudoAwareFirstChild(const Node* node) 190{ 191 if (node->isElementNode()) { 192 const Element* currentElement = toElement(node); 193 Node* first = currentElement->pseudoElement(BEFORE); 194 if (first) 195 return first; 196 first = firstChild(currentElement); 197 if (!first) 198 first = currentElement->pseudoElement(AFTER); 199 return first; 200 } 201 202 return firstChild(node); 203} 204 205Node* next(const Node* node, const Node* stayWithin) 206{ 207 if (Node* child = pseudoAwareFirstChild(node)) 208 return child; 209 if (node == stayWithin) 210 return 0; 211 if (Node* nextNode = pseudoAwareNextSibling(node)) 212 return nextNode; 213 for (Node* parentNode = parent(node); parentNode; parentNode = parent(parentNode)) { 214 if (parentNode == stayWithin) 215 return 0; 216 if (Node* nextNode = pseudoAwareNextSibling(parentNode)) 217 return nextNode; 218 } 219 return 0; 220} 221 222RenderObject* nextSiblingRenderer(const Node* node) 223{ 224 for (Node* sibling = NodeRenderingTraversal::nextSibling(node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) { 225 RenderObject* renderer = sibling->renderer(); 226 if (renderer && !isRendererReparented(renderer)) 227 return renderer; 228 } 229 return 0; 230} 231 232RenderObject* previousSiblingRenderer(const Node* node) 233{ 234 for (Node* sibling = NodeRenderingTraversal::previousSibling(node); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) { 235 RenderObject* renderer = sibling->renderer(); 236 if (renderer && !isRendererReparented(renderer)) 237 return renderer; 238 } 239 return 0; 240} 241 242RenderObject* nextInTopLayer(const Element* element) 243{ 244 if (!element->isInTopLayer()) 245 return 0; 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()) 251 return renderer; 252 } 253 return 0; 254} 255 256} 257 258} // namespace 259