From cad810f21b803229eb11403f9209855525a25d57 Mon Sep 17 00:00:00 2001 From: Steve Block Date: Fri, 6 May 2011 11:45:16 +0100 Subject: Merge WebKit at r75315: Initial merge by git. Change-Id: I570314b346ce101c935ed22a626b48c2af266b84 --- Source/WebCore/rendering/CounterNode.cpp | 272 +++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 Source/WebCore/rendering/CounterNode.cpp (limited to 'Source/WebCore/rendering/CounterNode.cpp') diff --git a/Source/WebCore/rendering/CounterNode.cpp b/Source/WebCore/rendering/CounterNode.cpp new file mode 100644 index 0000000..ac83d5a --- /dev/null +++ b/Source/WebCore/rendering/CounterNode.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "CounterNode.h" + +#include "RenderCounter.h" +#include "RenderObject.h" +#include + +namespace WebCore { + +CounterNode::CounterNode(RenderObject* o, bool hasResetType, int value) + : m_hasResetType(hasResetType) + , m_value(value) + , m_countInParent(0) + , m_renderer(o) + , m_parent(0) + , m_previousSibling(0) + , m_nextSibling(0) + , m_firstChild(0) + , m_lastChild(0) +{ +} + +PassRefPtr CounterNode::create(RenderObject* renderer, bool hasResetType, int value) +{ + return adoptRef(new CounterNode(renderer, hasResetType, value)); +} + +CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const +{ + if (this == stayWithin) + return 0; + + const CounterNode* current = this; + CounterNode* next; + while (!(next = current->m_nextSibling)) { + current = current->m_parent; + if (!current || current == stayWithin) + return 0; + } + return next; +} + +CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const +{ + if (CounterNode* next = m_firstChild) + return next; + + return nextInPreOrderAfterChildren(stayWithin); +} + +CounterNode* CounterNode::lastDescendant() const +{ + CounterNode* last = m_lastChild; + if (!last) + return 0; + + while (CounterNode* lastChild = last->m_lastChild) + last = lastChild; + + return last; +} + +CounterNode* CounterNode::previousInPreOrder() const +{ + CounterNode* previous = m_previousSibling; + if (!previous) + return m_parent; + + while (CounterNode* lastChild = previous->m_lastChild) + previous = lastChild; + + return previous; +} + +int CounterNode::computeCountInParent() const +{ + int increment = actsAsReset() ? 0 : m_value; + if (m_previousSibling) + return m_previousSibling->m_countInParent + increment; + ASSERT(m_parent->m_firstChild == this); + return m_parent->m_value + increment; +} + +void CounterNode::resetRenderer(const AtomicString& identifier) const +{ + if (!m_renderer || m_renderer->documentBeingDestroyed()) + return; + if (RenderObjectChildList* children = m_renderer->virtualChildren()) + children->invalidateCounters(m_renderer, identifier); +} + +void CounterNode::resetRenderers(const AtomicString& identifier) const +{ + const CounterNode* node = this; + do { + node->resetRenderer(identifier); + node = node->nextInPreOrder(this); + } while (node); +} + +void CounterNode::recount(const AtomicString& identifier) +{ + for (CounterNode* node = this; node; node = node->m_nextSibling) { + int oldCount = node->m_countInParent; + int newCount = node->computeCountInParent(); + if (oldCount == newCount) + break; + node->m_countInParent = newCount; + node->resetRenderers(identifier); + } +} + +void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, const AtomicString& identifier) +{ + ASSERT(newChild); + ASSERT(!newChild->m_parent); + ASSERT(!newChild->m_previousSibling); + ASSERT(!newChild->m_nextSibling); + ASSERT(!refChild || refChild->m_parent == this); + + if (newChild->m_hasResetType) { + while (m_lastChild != refChild) + RenderCounter::destroyCounterNode(m_lastChild->renderer(), identifier); + } + + CounterNode* next; + + if (refChild) { + next = refChild->m_nextSibling; + refChild->m_nextSibling = newChild; + } else { + next = m_firstChild; + m_firstChild = newChild; + } + + newChild->m_parent = this; + newChild->m_previousSibling = refChild; + + if (!newChild->m_firstChild || newChild->m_hasResetType) { + newChild->m_nextSibling = next; + if (next) { + ASSERT(next->m_previousSibling == refChild); + next->m_previousSibling = newChild; + } else { + ASSERT(m_lastChild == refChild); + m_lastChild = newChild; + } + + newChild->m_countInParent = newChild->computeCountInParent(); + newChild->resetRenderers(identifier); + if (next) + next->recount(identifier); + return; + } + + // The code below handles the case when a formerly root increment counter is loosing its root position + // and therefore its children become next siblings. + CounterNode* last = newChild->m_lastChild; + CounterNode* first = newChild->m_firstChild; + + newChild->m_nextSibling = first; + first->m_previousSibling = newChild; + // The case when the original next sibling of the inserted node becomes a child of + // one of the former children of the inserted node is not handled as it is believed + // to be impossible since: + // 1. if the increment counter node lost it's root position as a result of another + // counter node being created, it will be inserted as the last child so next is null. + // 2. if the increment counter node lost it's root position as a result of a renderer being + // inserted into the document's render tree, all its former children counters are attached + // to children of the inserted renderer and hence cannot be in scope for counter nodes + // attached to renderers that were already in the document's render tree. + last->m_nextSibling = next; + if (next) + next->m_previousSibling = last; + else + m_lastChild = last; + for (next = first; ; next = next->m_nextSibling) { + next->m_parent = this; + if (last == next) + break; + } + newChild->m_firstChild = 0; + newChild->m_lastChild = 0; + newChild->m_countInParent = newChild->computeCountInParent(); + newChild->resetRenderer(identifier); + first->recount(identifier); +} + +void CounterNode::removeChild(CounterNode* oldChild, const AtomicString& identifier) +{ + ASSERT(oldChild); + ASSERT(!oldChild->m_firstChild); + ASSERT(!oldChild->m_lastChild); + + CounterNode* next = oldChild->m_nextSibling; + CounterNode* previous = oldChild->m_previousSibling; + + oldChild->m_nextSibling = 0; + oldChild->m_previousSibling = 0; + oldChild->m_parent = 0; + + if (previous) + previous->m_nextSibling = next; + else { + ASSERT(m_firstChild == oldChild); + m_firstChild = next; + } + + if (next) + next->m_previousSibling = previous; + else { + ASSERT(m_lastChild == oldChild); + m_lastChild = previous; + } + + if (next) + next->recount(identifier); +} + +#ifndef NDEBUG + +static void showTreeAndMark(const CounterNode* node) +{ + const CounterNode* root = node; + while (root->parent()) + root = root->parent(); + + for (const CounterNode* current = root; current; current = current->nextInPreOrder()) { + fwrite((current == node) ? "*" : " ", 1, 1, stderr); + for (const CounterNode* parent = current; parent && parent != root; parent = parent->parent()) + fwrite(" ", 1, 2, stderr); + fprintf(stderr, "%p %s: %d %d P:%p PS:%p NS:%p R:%p\n", + current, current->actsAsReset() ? "reset____" : "increment", current->value(), + current->countInParent(), current->parent(), current->previousSibling(), + current->nextSibling(), current->renderer()); + } +} + +#endif + +} // namespace WebCore + +#ifndef NDEBUG + +void showTree(const WebCore::CounterNode* counter) +{ + if (counter) + showTreeAndMark(counter); +} + +#endif -- cgit v1.1