1 /*
2 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 *
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.
9 *
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.
14 *
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.
19 *
20 */
21
22 #include "config.h"
23 #include "core/rendering/CounterNode.h"
24
25 #include "core/rendering/RenderCounter.h"
26
27 #ifndef NDEBUG
28 #include <stdio.h>
29 #endif
30
31 namespace WebCore {
32
CounterNode(RenderObject & o,bool hasResetType,int value)33 CounterNode::CounterNode(RenderObject& o, bool hasResetType, int value)
34 : m_hasResetType(hasResetType)
35 , m_value(value)
36 , m_countInParent(0)
37 , m_owner(o)
38 , m_rootRenderer(0)
39 , m_parent(0)
40 , m_previousSibling(0)
41 , m_nextSibling(0)
42 , m_firstChild(0)
43 , m_lastChild(0)
44 {
45 }
46
~CounterNode()47 CounterNode::~CounterNode()
48 {
49 // Ideally this would be an assert and this would never be reached. In reality this happens a lot
50 // so we need to handle these cases. The node is still connected to the tree so we need to detach it.
51 if (m_parent || m_previousSibling || m_nextSibling || m_firstChild || m_lastChild) {
52 CounterNode* oldParent = 0;
53 CounterNode* oldPreviousSibling = 0;
54 // Instead of calling removeChild() we do this safely as the tree is likely broken if we get here.
55 if (m_parent) {
56 if (m_parent->m_firstChild == this)
57 m_parent->m_firstChild = m_nextSibling;
58 if (m_parent->m_lastChild == this)
59 m_parent->m_lastChild = m_previousSibling;
60 oldParent = m_parent;
61 m_parent = 0;
62 }
63 if (m_previousSibling) {
64 if (m_previousSibling->m_nextSibling == this)
65 m_previousSibling->m_nextSibling = m_nextSibling;
66 oldPreviousSibling = m_previousSibling;
67 m_previousSibling = 0;
68 }
69 if (m_nextSibling) {
70 if (m_nextSibling->m_previousSibling == this)
71 m_nextSibling->m_previousSibling = oldPreviousSibling;
72 m_nextSibling = 0;
73 }
74 if (m_firstChild) {
75 // The node's children are reparented to the old parent.
76 for (CounterNode* child = m_firstChild; child; ) {
77 CounterNode* nextChild = child->m_nextSibling;
78 CounterNode* nextSibling = 0;
79 child->m_parent = oldParent;
80 if (oldPreviousSibling) {
81 nextSibling = oldPreviousSibling->m_nextSibling;
82 child->m_previousSibling = oldPreviousSibling;
83 oldPreviousSibling->m_nextSibling = child;
84 child->m_nextSibling = nextSibling;
85 nextSibling->m_previousSibling = child;
86 oldPreviousSibling = child;
87 }
88 child = nextChild;
89 }
90 }
91 }
92 resetRenderers();
93 }
94
create(RenderObject & owner,bool hasResetType,int value)95 PassRefPtr<CounterNode> CounterNode::create(RenderObject& owner, bool hasResetType, int value)
96 {
97 return adoptRef(new CounterNode(owner, hasResetType, value));
98 }
99
nextInPreOrderAfterChildren(const CounterNode * stayWithin) const100 CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const
101 {
102 if (this == stayWithin)
103 return 0;
104
105 const CounterNode* current = this;
106 CounterNode* next;
107 while (!(next = current->m_nextSibling)) {
108 current = current->m_parent;
109 if (!current || current == stayWithin)
110 return 0;
111 }
112 return next;
113 }
114
nextInPreOrder(const CounterNode * stayWithin) const115 CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const
116 {
117 if (CounterNode* next = m_firstChild)
118 return next;
119
120 return nextInPreOrderAfterChildren(stayWithin);
121 }
122
lastDescendant() const123 CounterNode* CounterNode::lastDescendant() const
124 {
125 CounterNode* last = m_lastChild;
126 if (!last)
127 return 0;
128
129 while (CounterNode* lastChild = last->m_lastChild)
130 last = lastChild;
131
132 return last;
133 }
134
previousInPreOrder() const135 CounterNode* CounterNode::previousInPreOrder() const
136 {
137 CounterNode* previous = m_previousSibling;
138 if (!previous)
139 return m_parent;
140
141 while (CounterNode* lastChild = previous->m_lastChild)
142 previous = lastChild;
143
144 return previous;
145 }
146
computeCountInParent() const147 int CounterNode::computeCountInParent() const
148 {
149 int increment = actsAsReset() ? 0 : m_value;
150 if (m_previousSibling)
151 return m_previousSibling->m_countInParent + increment;
152 ASSERT(m_parent->m_firstChild == this);
153 return m_parent->m_value + increment;
154 }
155
addRenderer(RenderCounter * value)156 void CounterNode::addRenderer(RenderCounter* value)
157 {
158 if (!value) {
159 ASSERT_NOT_REACHED();
160 return;
161 }
162 if (value->m_counterNode) {
163 ASSERT_NOT_REACHED();
164 value->m_counterNode->removeRenderer(value);
165 }
166 ASSERT(!value->m_nextForSameCounter);
167 for (RenderCounter* iterator = m_rootRenderer;iterator; iterator = iterator->m_nextForSameCounter) {
168 if (iterator == value) {
169 ASSERT_NOT_REACHED();
170 return;
171 }
172 }
173 value->m_nextForSameCounter = m_rootRenderer;
174 m_rootRenderer = value;
175 if (value->m_counterNode != this) {
176 if (value->m_counterNode) {
177 ASSERT_NOT_REACHED();
178 value->m_counterNode->removeRenderer(value);
179 }
180 value->m_counterNode = this;
181 }
182 }
183
removeRenderer(RenderCounter * value)184 void CounterNode::removeRenderer(RenderCounter* value)
185 {
186 if (!value) {
187 ASSERT_NOT_REACHED();
188 return;
189 }
190 if (value->m_counterNode && value->m_counterNode != this) {
191 ASSERT_NOT_REACHED();
192 value->m_counterNode->removeRenderer(value);
193 }
194 RenderCounter* previous = 0;
195 for (RenderCounter* iterator = m_rootRenderer;iterator; iterator = iterator->m_nextForSameCounter) {
196 if (iterator == value) {
197 if (previous)
198 previous->m_nextForSameCounter = value->m_nextForSameCounter;
199 else
200 m_rootRenderer = value->m_nextForSameCounter;
201 value->m_nextForSameCounter = 0;
202 value->m_counterNode = 0;
203 return;
204 }
205 previous = iterator;
206 }
207 ASSERT_NOT_REACHED();
208 }
209
resetRenderers()210 void CounterNode::resetRenderers()
211 {
212 while (m_rootRenderer)
213 m_rootRenderer->invalidate(); // This makes m_rootRenderer point to the next renderer if any since it disconnects the m_rootRenderer from this.
214 }
215
resetThisAndDescendantsRenderers()216 void CounterNode::resetThisAndDescendantsRenderers()
217 {
218 CounterNode* node = this;
219 do {
220 node->resetRenderers();
221 node = node->nextInPreOrder(this);
222 } while (node);
223 }
224
recount()225 void CounterNode::recount()
226 {
227 for (CounterNode* node = this; node; node = node->m_nextSibling) {
228 int oldCount = node->m_countInParent;
229 int newCount = node->computeCountInParent();
230 if (oldCount == newCount)
231 break;
232 node->m_countInParent = newCount;
233 node->resetThisAndDescendantsRenderers();
234 }
235 }
236
insertAfter(CounterNode * newChild,CounterNode * refChild,const AtomicString & identifier)237 void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, const AtomicString& identifier)
238 {
239 ASSERT(newChild);
240 ASSERT(!newChild->m_parent);
241 ASSERT(!newChild->m_previousSibling);
242 ASSERT(!newChild->m_nextSibling);
243 // If the refChild is not our child we can not complete the request. This hardens against bugs in RenderCounter.
244 // When renderers are reparented it may request that we insert counter nodes improperly.
245 if (refChild && refChild->m_parent != this)
246 return;
247
248 if (newChild->m_hasResetType) {
249 while (m_lastChild != refChild)
250 RenderCounter::destroyCounterNode(m_lastChild->owner(), identifier);
251 }
252
253 CounterNode* next;
254
255 if (refChild) {
256 next = refChild->m_nextSibling;
257 refChild->m_nextSibling = newChild;
258 } else {
259 next = m_firstChild;
260 m_firstChild = newChild;
261 }
262
263 newChild->m_parent = this;
264 newChild->m_previousSibling = refChild;
265
266 if (next) {
267 ASSERT(next->m_previousSibling == refChild);
268 next->m_previousSibling = newChild;
269 newChild->m_nextSibling = next;
270 } else {
271 ASSERT(m_lastChild == refChild);
272 m_lastChild = newChild;
273 }
274
275 if (!newChild->m_firstChild || newChild->m_hasResetType) {
276 newChild->m_countInParent = newChild->computeCountInParent();
277 newChild->resetThisAndDescendantsRenderers();
278 if (next)
279 next->recount();
280 return;
281 }
282
283 // The code below handles the case when a formerly root increment counter is loosing its root position
284 // and therefore its children become next siblings.
285 CounterNode* last = newChild->m_lastChild;
286 CounterNode* first = newChild->m_firstChild;
287
288 if (first) {
289 ASSERT(last);
290 newChild->m_nextSibling = first;
291 if (m_lastChild == newChild)
292 m_lastChild = last;
293
294 first->m_previousSibling = newChild;
295
296 // The case when the original next sibling of the inserted node becomes a child of
297 // one of the former children of the inserted node is not handled as it is believed
298 // to be impossible since:
299 // 1. if the increment counter node lost it's root position as a result of another
300 // counter node being created, it will be inserted as the last child so next is null.
301 // 2. if the increment counter node lost it's root position as a result of a renderer being
302 // inserted into the document's render tree, all its former children counters are attached
303 // to children of the inserted renderer and hence cannot be in scope for counter nodes
304 // attached to renderers that were already in the document's render tree.
305 last->m_nextSibling = next;
306 if (next) {
307 ASSERT(next->m_previousSibling == newChild);
308 next->m_previousSibling = last;
309 } else
310 m_lastChild = last;
311 for (next = first; ; next = next->m_nextSibling) {
312 next->m_parent = this;
313 if (last == next)
314 break;
315 }
316 }
317 newChild->m_firstChild = 0;
318 newChild->m_lastChild = 0;
319 newChild->m_countInParent = newChild->computeCountInParent();
320 newChild->resetRenderers();
321 first->recount();
322 }
323
removeChild(CounterNode * oldChild)324 void CounterNode::removeChild(CounterNode* oldChild)
325 {
326 ASSERT(oldChild);
327 ASSERT(!oldChild->m_firstChild);
328 ASSERT(!oldChild->m_lastChild);
329
330 CounterNode* next = oldChild->m_nextSibling;
331 CounterNode* previous = oldChild->m_previousSibling;
332
333 oldChild->m_nextSibling = 0;
334 oldChild->m_previousSibling = 0;
335 oldChild->m_parent = 0;
336
337 if (previous)
338 previous->m_nextSibling = next;
339 else {
340 ASSERT(m_firstChild == oldChild);
341 m_firstChild = next;
342 }
343
344 if (next)
345 next->m_previousSibling = previous;
346 else {
347 ASSERT(m_lastChild == oldChild);
348 m_lastChild = previous;
349 }
350
351 if (next)
352 next->recount();
353 }
354
355 #ifndef NDEBUG
356
showTreeAndMark(const CounterNode * node)357 static void showTreeAndMark(const CounterNode* node)
358 {
359 const CounterNode* root = node;
360 while (root->parent())
361 root = root->parent();
362
363 for (const CounterNode* current = root; current; current = current->nextInPreOrder()) {
364 fprintf(stderr, "%c", (current == node) ? '*' : ' ');
365 for (const CounterNode* parent = current; parent && parent != root; parent = parent->parent())
366 fprintf(stderr, " ");
367 fprintf(stderr, "%p %s: %d %d P:%p PS:%p NS:%p R:%p\n",
368 current, current->actsAsReset() ? "reset____" : "increment", current->value(),
369 current->countInParent(), current->parent(), current->previousSibling(),
370 current->nextSibling(), ¤t->owner());
371 }
372 fflush(stderr);
373 }
374
375 #endif
376
377 } // namespace WebCore
378
379 #ifndef NDEBUG
380
showCounterTree(const WebCore::CounterNode * counter)381 void showCounterTree(const WebCore::CounterNode* counter)
382 {
383 if (counter)
384 showTreeAndMark(counter);
385 }
386
387 #endif
388