/* * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "sky/engine/config.h" #include "sky/engine/core/dom/NodeRenderingTraversal.h" #include "sky/engine/core/dom/shadow/ComposedTreeWalker.h" #include "sky/engine/core/rendering/RenderObject.h" namespace blink { namespace NodeRenderingTraversal { void ParentDetails::didTraverseInsertionPoint(const InsertionPoint* insertionPoint) { if (!m_insertionPoint) { m_insertionPoint = insertionPoint; } } ContainerNode* parent(const Node* node, ParentDetails* details) { ASSERT(node); ASSERT(!node->document().childNeedsDistributionRecalc()); if (isActiveInsertionPoint(*node)) return 0; ComposedTreeWalker walker(node, ComposedTreeWalker::CanStartFromShadowBoundary); return toContainerNode(walker.traverseParent(walker.get(), details)); } bool contains(const ContainerNode* container, const Node* node) { while (node) { if (node == container) return true; node = NodeRenderingTraversal::parent(node); } return false; } Node* nextSibling(const Node* node) { ComposedTreeWalker walker(node); walker.nextSibling(); return walker.get(); } Node* previousSibling(const Node* node) { ComposedTreeWalker walker(node); walker.previousSibling(); return walker.get(); } static Node* lastChild(const Node* node) { ComposedTreeWalker walker(node); walker.lastChild(); return walker.get(); } static Node* firstChild(const Node* node) { ComposedTreeWalker walker(node); walker.firstChild(); return walker.get(); } Node* previous(const Node* node, const Node* stayWithin) { if (node == stayWithin) return 0; if (Node* previousNode = previousSibling(node)) { while (Node* previousLastChild = lastChild(previousNode)) previousNode = previousLastChild; return previousNode; } return parent(node); } Node* next(const Node* node, const Node* stayWithin) { if (Node* child = firstChild(node)) return child; if (node == stayWithin) return 0; if (Node* nextNode = nextSibling(node)) return nextNode; for (Node* parentNode = parent(node); parentNode; parentNode = parent(parentNode)) { if (parentNode == stayWithin) return 0; if (Node* nextNode = nextSibling(parentNode)) return nextNode; } return 0; } RenderObject* nextSiblingRenderer(const Node* node) { for (Node* sibling = NodeRenderingTraversal::nextSibling(node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) { if (RenderObject* renderer = sibling->renderer()) return renderer; } return 0; } RenderObject* previousSiblingRenderer(const Node* node) { for (Node* sibling = NodeRenderingTraversal::previousSibling(node); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) { if (RenderObject* renderer = sibling->renderer()) return renderer; } return 0; } Node* commonAncestor(Node& a, Node& b) { if (a == b) return &a; if (a.document() != b.document()) return 0; int thisDepth = 0; for (Node* node = &a; node; node = parent(node)) { if (node == b) return node; thisDepth++; } int otherDepth = 0; for (const Node* node = &b; node; node = parent(node)) { if (node == a) return &a; otherDepth++; } Node* thisIterator = &a; const Node* otherIterator = &b; if (thisDepth > otherDepth) { for (int i = thisDepth; i > otherDepth; --i) thisIterator = parent(thisIterator); } else if (otherDepth > thisDepth) { for (int i = otherDepth; i > thisDepth; --i) otherIterator = parent(otherIterator); } while (thisIterator) { if (thisIterator == otherIterator) return thisIterator; thisIterator = parent(thisIterator); otherIterator = parent(otherIterator); } ASSERT(!otherIterator); return 0; } } } // namespace