2 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
23 #include "CounterNode.h"
25 #include "RenderObject.h"
28 // FIXME: There's currently no strategy for getting the counter tree updated when new
29 // elements with counter-reset and counter-increment styles are added to the render tree.
30 // Also, the code can't handle changes where an existing node needs to change into a
31 // "reset" node, or from a "reset" node back to not a "reset" node. As of this writing,
32 // at least some of these problems manifest as failures in the t1204-increment and
33 // t1204-reset tests in the CSS 2.1 test suite.
37 CounterNode::CounterNode(RenderObject* o, bool isReset, int value)
43 , m_previousSibling(0)
50 CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const
52 if (this == stayWithin)
55 CounterNode* next = m_nextSibling;
59 while (next && !next->m_nextSibling) {
60 if (next == stayWithin)
62 next = next->m_parent;
65 return next->m_nextSibling;
69 CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const
71 if (CounterNode* next = m_firstChild)
74 return nextInPreOrderAfterChildren(stayWithin);
77 CounterNode* CounterNode::lastDescendant() const
79 CounterNode* last = m_lastChild;
83 while (CounterNode* lastChild = last->m_lastChild)
89 CounterNode* CounterNode::previousInPreOrder() const
91 CounterNode* previous = m_previousSibling;
95 while (CounterNode* lastChild = previous->m_lastChild)
101 int CounterNode::computeCountInParent() const
103 int increment = m_isReset ? 0 : m_value;
104 if (m_previousSibling)
105 return m_previousSibling->m_countInParent + increment;
106 ASSERT(m_parent->m_firstChild == this);
107 return m_parent->m_value + increment;
111 void CounterNode::resetRenderer(const AtomicString& identifier) const
113 if (!m_renderer || m_renderer->documentBeingDestroyed())
115 if (RenderObjectChildList* children = m_renderer->virtualChildren())
116 children->invalidateCounters(m_renderer, identifier);
119 void CounterNode::resetRenderers(const AtomicString& identifier) const
121 const CounterNode* node = this;
123 node->resetRenderer(identifier);
124 node = node->nextInPreOrder(this);
128 void CounterNode::recount(const AtomicString& identifier)
130 for (CounterNode* node = this; node; node = node->m_nextSibling) {
131 int oldCount = node->m_countInParent;
132 int newCount = node->computeCountInParent();
133 if (oldCount == newCount)
135 node->m_countInParent = newCount;
136 node->resetRenderers(identifier);
140 void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, const AtomicString& identifier)
143 ASSERT(!newChild->m_parent);
144 ASSERT(!newChild->m_previousSibling);
145 ASSERT(!newChild->m_nextSibling);
146 ASSERT(!refChild || refChild->m_parent == this);
151 next = refChild->m_nextSibling;
152 refChild->m_nextSibling = newChild;
155 m_firstChild = newChild;
159 ASSERT(next->m_previousSibling == refChild);
160 next->m_previousSibling = newChild;
162 ASSERT(m_lastChild == refChild);
163 m_lastChild = newChild;
166 newChild->m_parent = this;
167 newChild->m_previousSibling = refChild;
168 newChild->m_nextSibling = next;
170 newChild->m_countInParent = newChild->computeCountInParent();
172 next->recount(identifier);
175 void CounterNode::removeChild(CounterNode* oldChild, const AtomicString& identifier)
178 ASSERT(!oldChild->m_firstChild);
179 ASSERT(!oldChild->m_lastChild);
181 CounterNode* next = oldChild->m_nextSibling;
182 CounterNode* previous = oldChild->m_previousSibling;
184 oldChild->m_nextSibling = 0;
185 oldChild->m_previousSibling = 0;
186 oldChild->m_parent = 0;
189 previous->m_nextSibling = next;
191 ASSERT(m_firstChild == oldChild);
196 next->m_previousSibling = previous;
198 ASSERT(m_lastChild == oldChild);
199 m_lastChild = previous;
203 next->recount(identifier);
208 static void showTreeAndMark(const CounterNode* node)
210 const CounterNode* root = node;
211 while (root->parent())
212 root = root->parent();
214 for (const CounterNode* current = root; current; current = nextInPreOrder(current)) {
215 fwrite((current == node) ? "*" : " ", 1, 1, stderr);
216 for (const CounterNode* parent = current; parent && parent != root; parent = parent->parent())
217 fwrite(" ", 1, 2, stderr);
218 fprintf(stderr, "%p %s: %d %d P:%p PS:%p NS:%p R:%p\n",
219 current, current->isReset() ? "reset____" : "increment", current->value(),
220 current->countInParent(), current->parent(), current->previousSibling(),
221 current->nextSibling(), current->renderer());
227 } // namespace WebCore
231 void showTree(const WebCore::CounterNode* counter)
234 showTreeAndMark(counter);