diff options
Diffstat (limited to 'WebCore/rendering/CounterNode.cpp')
-rw-r--r-- | WebCore/rendering/CounterNode.cpp | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/WebCore/rendering/CounterNode.cpp b/WebCore/rendering/CounterNode.cpp new file mode 100644 index 0000000..c30ca9a --- /dev/null +++ b/WebCore/rendering/CounterNode.cpp @@ -0,0 +1,192 @@ +/* + * This file is part of the HTML rendering engine for KDE. + * + * 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 "RenderObject.h" +#include <stdio.h> + +// FIXME: There's currently no strategy for getting the counter tree updated when new +// elements with counter-reset and counter-increment styles are added to the render tree. +// Also, the code can't handle changes where an existing node needs to change into a +// "reset" node, or from a "reset" node back to not a "reset" node. As of this writing, +// at least some of these problems manifest as failures in the t1204-increment and +// t1204-reset tests in the CSS 2.1 test suite. + +namespace WebCore { + +CounterNode::CounterNode(RenderObject* o, bool isReset, int value) + : m_isReset(isReset) + , m_value(value) + , m_countInParent(0) + , m_renderer(o) + , m_parent(0) + , m_previousSibling(0) + , m_nextSibling(0) + , m_firstChild(0) + , m_lastChild(0) +{ +} + +int CounterNode::computeCountInParent() const +{ + int increment = m_isReset ? 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::recount() +{ + for (CounterNode* c = this; c; c = c->m_nextSibling) { + int oldCount = c->m_countInParent; + int newCount = c->computeCountInParent(); + c->m_countInParent = newCount; + if (oldCount == newCount) + break; + if (c->m_renderer->isCounter()) + c->m_renderer->setNeedsLayoutAndPrefWidthsRecalc(); + } +} + +void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild) +{ + ASSERT(newChild); + ASSERT(!newChild->m_parent); + ASSERT(!newChild->m_previousSibling); + ASSERT(!newChild->m_nextSibling); + ASSERT(!refChild || refChild->m_parent == this); + + CounterNode* next; + + if (refChild) { + next = refChild->m_nextSibling; + refChild->m_nextSibling = newChild; + } else { + next = m_firstChild; + m_firstChild = newChild; + } + + if (next) { + ASSERT(next->m_previousSibling == refChild); + next->m_previousSibling = newChild; + } else { + ASSERT(m_lastChild == refChild); + m_lastChild = newChild; + } + + newChild->m_parent = this; + newChild->m_previousSibling = refChild; + newChild->m_nextSibling = next; + + newChild->m_countInParent = newChild->computeCountInParent(); + if (next) + next->recount(); +} + +void CounterNode::removeChild(CounterNode* oldChild) +{ + ASSERT(oldChild); + ASSERT(!oldChild->m_firstChild); + ASSERT(!oldChild->m_lastChild); + + CounterNode* next = oldChild->m_nextSibling; + CounterNode* prev = oldChild->m_previousSibling; + + oldChild->m_nextSibling = 0; + oldChild->m_previousSibling = 0; + oldChild->m_parent = 0; + + if (prev) + prev->m_nextSibling = next; + else { + ASSERT(m_firstChild == oldChild); + m_firstChild = next; + } + + if (next) + next->m_previousSibling = prev; + else { + ASSERT(m_lastChild == oldChild); + m_lastChild = prev; + } + + if (next) + next->recount(); +} + +#ifndef NDEBUG + +static const CounterNode* nextInPreOrderAfterChildren(const CounterNode* node) +{ + CounterNode* next = node->nextSibling(); + if (!next) { + next = node->parent(); + while (next && !next->nextSibling()) + next = next->parent(); + if (next) + next = next->nextSibling(); + } + return next; +} + +static const CounterNode* nextInPreOrder(const CounterNode* node) +{ + if (CounterNode* child = node->firstChild()) + return child; + return nextInPreOrderAfterChildren(node); +} + +static void showTreeAndMark(const CounterNode* node) +{ + const CounterNode* root = node; + while (root->parent()) + root = root->parent(); + + for (const CounterNode* c = root; c; c = nextInPreOrder(c)) { + if (c == node) + fprintf(stderr, "*"); + for (const CounterNode* d = c; d && d != root; d = d->parent()) + fprintf(stderr, "\t"); + if (c->isReset()) + fprintf(stderr, "reset: %d\n", c->value()); + else + fprintf(stderr, "increment: %d\n", c->value()); + } +} + +#endif + +} // namespace WebCore + +#ifndef NDEBUG + +void showTree(const WebCore::CounterNode* counter) +{ + if (counter) + showTreeAndMark(counter); +} + +#endif |