OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 2 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | 3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 24 matching lines...) Expand all Loading... | |
35 m_countInParent(0), | 35 m_countInParent(0), |
36 m_owner(o), | 36 m_owner(o), |
37 m_rootLayoutObject(nullptr), | 37 m_rootLayoutObject(nullptr), |
38 m_parent(nullptr), | 38 m_parent(nullptr), |
39 m_previousSibling(nullptr), | 39 m_previousSibling(nullptr), |
40 m_nextSibling(nullptr), | 40 m_nextSibling(nullptr), |
41 m_firstChild(nullptr), | 41 m_firstChild(nullptr), |
42 m_lastChild(nullptr) {} | 42 m_lastChild(nullptr) {} |
43 | 43 |
44 CounterNode::~CounterNode() { | 44 CounterNode::~CounterNode() { |
45 // Ideally this would be an assert and this would never be reached. In reality this happens a lot | 45 // Ideally this would be an assert and this would never be reached. In reality |
46 // so we need to handle these cases. The node is still connected to the tree s o we need to detach it. | 46 // this happens a lot so we need to handle these cases. The node is still |
47 // connected to the tree so we need to detach it. | |
47 if (m_parent || m_previousSibling || m_nextSibling || m_firstChild || | 48 if (m_parent || m_previousSibling || m_nextSibling || m_firstChild || |
48 m_lastChild) { | 49 m_lastChild) { |
49 CounterNode* oldParent = nullptr; | 50 CounterNode* oldParent = nullptr; |
50 CounterNode* oldPreviousSibling = nullptr; | 51 CounterNode* oldPreviousSibling = nullptr; |
51 // Instead of calling removeChild() we do this safely as the tree is likely broken if we get here. | 52 // Instead of calling removeChild() we do this safely as the tree is likely |
53 // broken if we get here. | |
52 if (m_parent) { | 54 if (m_parent) { |
53 if (m_parent->m_firstChild == this) | 55 if (m_parent->m_firstChild == this) |
54 m_parent->m_firstChild = m_nextSibling; | 56 m_parent->m_firstChild = m_nextSibling; |
55 if (m_parent->m_lastChild == this) | 57 if (m_parent->m_lastChild == this) |
56 m_parent->m_lastChild = m_previousSibling; | 58 m_parent->m_lastChild = m_previousSibling; |
57 oldParent = m_parent; | 59 oldParent = m_parent; |
58 m_parent = nullptr; | 60 m_parent = nullptr; |
59 } | 61 } |
60 if (m_previousSibling) { | 62 if (m_previousSibling) { |
61 if (m_previousSibling->m_nextSibling == this) | 63 if (m_previousSibling->m_nextSibling == this) |
(...skipping 21 matching lines...) Expand all Loading... | |
83 oldPreviousSibling = child; | 85 oldPreviousSibling = child; |
84 } | 86 } |
85 child = nextChild; | 87 child = nextChild; |
86 } | 88 } |
87 } | 89 } |
88 } | 90 } |
89 resetLayoutObjects(); | 91 resetLayoutObjects(); |
90 } | 92 } |
91 | 93 |
92 PassRefPtr<CounterNode> CounterNode::create(LayoutObject& owner, | 94 PassRefPtr<CounterNode> CounterNode::create(LayoutObject& owner, |
93 bool hasResetType, | 95 bool hasResetType, int value) { |
94 int value) { | |
95 return adoptRef(new CounterNode(owner, hasResetType, value)); | 96 return adoptRef(new CounterNode(owner, hasResetType, value)); |
96 } | 97 } |
97 | 98 |
98 CounterNode* CounterNode::nextInPreOrderAfterChildren( | 99 CounterNode* CounterNode::nextInPreOrderAfterChildren( |
99 const CounterNode* stayWithin) const { | 100 const CounterNode* stayWithin) const { |
100 if (this == stayWithin) | 101 if (this == stayWithin) return nullptr; |
101 return nullptr; | |
102 | 102 |
103 const CounterNode* current = this; | 103 const CounterNode* current = this; |
104 CounterNode* next = current->m_nextSibling; | 104 CounterNode* next = current->m_nextSibling; |
105 for (; !next; next = current->m_nextSibling) { | 105 for (; !next; next = current->m_nextSibling) { |
106 current = current->m_parent; | 106 current = current->m_parent; |
107 if (!current || current == stayWithin) | 107 if (!current || current == stayWithin) return nullptr; |
108 return nullptr; | |
109 } | 108 } |
110 return next; | 109 return next; |
111 } | 110 } |
112 | 111 |
113 CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const { | 112 CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const { |
114 if (CounterNode* next = m_firstChild) | 113 if (CounterNode* next = m_firstChild) return next; |
115 return next; | |
116 | 114 |
117 return nextInPreOrderAfterChildren(stayWithin); | 115 return nextInPreOrderAfterChildren(stayWithin); |
118 } | 116 } |
119 | 117 |
120 CounterNode* CounterNode::lastDescendant() const { | 118 CounterNode* CounterNode::lastDescendant() const { |
121 CounterNode* last = m_lastChild; | 119 CounterNode* last = m_lastChild; |
122 if (!last) | 120 if (!last) return nullptr; |
123 return nullptr; | |
124 | 121 |
125 while (CounterNode* lastChild = last->m_lastChild) | 122 while (CounterNode* lastChild = last->m_lastChild) last = lastChild; |
126 last = lastChild; | |
127 | 123 |
128 return last; | 124 return last; |
129 } | 125 } |
130 | 126 |
131 CounterNode* CounterNode::previousInPreOrder() const { | 127 CounterNode* CounterNode::previousInPreOrder() const { |
132 CounterNode* previous = m_previousSibling; | 128 CounterNode* previous = m_previousSibling; |
133 if (!previous) | 129 if (!previous) return m_parent; |
134 return m_parent; | |
135 | 130 |
136 while (CounterNode* lastChild = previous->m_lastChild) | 131 while (CounterNode* lastChild = previous->m_lastChild) previous = lastChild; |
137 previous = lastChild; | |
138 | 132 |
139 return previous; | 133 return previous; |
140 } | 134 } |
141 | 135 |
142 int CounterNode::computeCountInParent() const { | 136 int CounterNode::computeCountInParent() const { |
143 int increment = actsAsReset() ? 0 : m_value; | 137 int increment = actsAsReset() ? 0 : m_value; |
144 if (m_previousSibling) | 138 if (m_previousSibling) return m_previousSibling->m_countInParent + increment; |
145 return m_previousSibling->m_countInParent + increment; | |
146 ASSERT(m_parent->m_firstChild == this); | 139 ASSERT(m_parent->m_firstChild == this); |
147 return m_parent->m_value + increment; | 140 return m_parent->m_value + increment; |
148 } | 141 } |
149 | 142 |
150 void CounterNode::addLayoutObject(LayoutCounter* value) { | 143 void CounterNode::addLayoutObject(LayoutCounter* value) { |
151 if (!value) { | 144 if (!value) { |
152 ASSERT_NOT_REACHED(); | 145 ASSERT_NOT_REACHED(); |
153 return; | 146 return; |
154 } | 147 } |
155 if (value->m_counterNode) { | 148 if (value->m_counterNode) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 value->m_counterNode = nullptr; | 189 value->m_counterNode = nullptr; |
197 return; | 190 return; |
198 } | 191 } |
199 previous = iterator; | 192 previous = iterator; |
200 } | 193 } |
201 ASSERT_NOT_REACHED(); | 194 ASSERT_NOT_REACHED(); |
202 } | 195 } |
203 | 196 |
204 void CounterNode::resetLayoutObjects() { | 197 void CounterNode::resetLayoutObjects() { |
205 while (m_rootLayoutObject) | 198 while (m_rootLayoutObject) |
206 m_rootLayoutObject | 199 m_rootLayoutObject->invalidate(); // This makes m_rootLayoutObject point to |
ikilpatrick
2016/10/04 16:39:02
nit. comment should be above line.
| |
207 ->invalidate(); // This makes m_rootLayoutObject point to the next layo utObject if any since it disconnects the m_rootLayoutObject from this. | 200 // the next layoutObject if any since it |
201 // disconnects the m_rootLayoutObject | |
202 // from this. | |
208 } | 203 } |
209 | 204 |
210 void CounterNode::resetThisAndDescendantsLayoutObjects() { | 205 void CounterNode::resetThisAndDescendantsLayoutObjects() { |
211 CounterNode* node = this; | 206 CounterNode* node = this; |
212 do { | 207 do { |
213 node->resetLayoutObjects(); | 208 node->resetLayoutObjects(); |
214 node = node->nextInPreOrder(this); | 209 node = node->nextInPreOrder(this); |
215 } while (node); | 210 } while (node); |
216 } | 211 } |
217 | 212 |
218 void CounterNode::recount() { | 213 void CounterNode::recount() { |
219 for (CounterNode* node = this; node; node = node->m_nextSibling) { | 214 for (CounterNode* node = this; node; node = node->m_nextSibling) { |
220 int oldCount = node->m_countInParent; | 215 int oldCount = node->m_countInParent; |
221 int newCount = node->computeCountInParent(); | 216 int newCount = node->computeCountInParent(); |
222 if (oldCount == newCount) | 217 if (oldCount == newCount) break; |
223 break; | |
224 node->m_countInParent = newCount; | 218 node->m_countInParent = newCount; |
225 node->resetThisAndDescendantsLayoutObjects(); | 219 node->resetThisAndDescendantsLayoutObjects(); |
226 } | 220 } |
227 } | 221 } |
228 | 222 |
229 void CounterNode::insertAfter(CounterNode* newChild, | 223 void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, |
230 CounterNode* refChild, | |
231 const AtomicString& identifier) { | 224 const AtomicString& identifier) { |
232 ASSERT(newChild); | 225 ASSERT(newChild); |
233 ASSERT(!newChild->m_parent); | 226 ASSERT(!newChild->m_parent); |
234 ASSERT(!newChild->m_previousSibling); | 227 ASSERT(!newChild->m_previousSibling); |
235 ASSERT(!newChild->m_nextSibling); | 228 ASSERT(!newChild->m_nextSibling); |
236 // If the refChild is not our child we can not complete the request. This hard ens against bugs in LayoutCounter. | 229 // If the refChild is not our child we can not complete the request. This |
237 // When layoutObjects are reparented it may request that we insert counter nod es improperly. | 230 // hardens against bugs in LayoutCounter. |
238 if (refChild && refChild->m_parent != this) | 231 // When layoutObjects are reparented it may request that we insert counter |
239 return; | 232 // nodes improperly. |
233 if (refChild && refChild->m_parent != this) return; | |
240 | 234 |
241 if (newChild->m_hasResetType) { | 235 if (newChild->m_hasResetType) { |
242 while (m_lastChild != refChild) | 236 while (m_lastChild != refChild) |
243 LayoutCounter::destroyCounterNode(m_lastChild->owner(), identifier); | 237 LayoutCounter::destroyCounterNode(m_lastChild->owner(), identifier); |
244 } | 238 } |
245 | 239 |
246 CounterNode* next; | 240 CounterNode* next; |
247 | 241 |
248 if (refChild) { | 242 if (refChild) { |
249 next = refChild->m_nextSibling; | 243 next = refChild->m_nextSibling; |
(...skipping 11 matching lines...) Expand all Loading... | |
261 next->m_previousSibling = newChild; | 255 next->m_previousSibling = newChild; |
262 newChild->m_nextSibling = next; | 256 newChild->m_nextSibling = next; |
263 } else { | 257 } else { |
264 ASSERT(m_lastChild == refChild); | 258 ASSERT(m_lastChild == refChild); |
265 m_lastChild = newChild; | 259 m_lastChild = newChild; |
266 } | 260 } |
267 | 261 |
268 if (!newChild->m_firstChild || newChild->m_hasResetType) { | 262 if (!newChild->m_firstChild || newChild->m_hasResetType) { |
269 newChild->m_countInParent = newChild->computeCountInParent(); | 263 newChild->m_countInParent = newChild->computeCountInParent(); |
270 newChild->resetThisAndDescendantsLayoutObjects(); | 264 newChild->resetThisAndDescendantsLayoutObjects(); |
271 if (next) | 265 if (next) next->recount(); |
272 next->recount(); | |
273 return; | 266 return; |
274 } | 267 } |
275 | 268 |
276 // The code below handles the case when a formerly root increment counter is l oosing its root position | 269 // The code below handles the case when a formerly root increment counter is |
277 // and therefore its children become next siblings. | 270 // loosing its root position and therefore its children become next siblings. |
278 CounterNode* last = newChild->m_lastChild; | 271 CounterNode* last = newChild->m_lastChild; |
279 CounterNode* first = newChild->m_firstChild; | 272 CounterNode* first = newChild->m_firstChild; |
280 | 273 |
281 if (first) { | 274 if (first) { |
282 ASSERT(last); | 275 ASSERT(last); |
283 newChild->m_nextSibling = first; | 276 newChild->m_nextSibling = first; |
284 if (m_lastChild == newChild) | 277 if (m_lastChild == newChild) m_lastChild = last; |
285 m_lastChild = last; | |
286 | 278 |
287 first->m_previousSibling = newChild; | 279 first->m_previousSibling = newChild; |
288 | 280 |
289 // The case when the original next sibling of the inserted node becomes a ch ild of | 281 // The case when the original next sibling of the inserted node becomes a |
290 // one of the former children of the inserted node is not handled as it is b elieved | 282 // child of one of the former children of the inserted node is not handled |
291 // to be impossible since: | 283 // as it is believed to be impossible since: |
292 // 1. if the increment counter node lost it's root position as a result of a nother | 284 // 1. if the increment counter node lost it's root position as a result of |
293 // counter node being created, it will be inserted as the last child so n ext is null. | 285 // another counter node being created, it will be inserted as the last |
294 // 2. if the increment counter node lost it's root position as a result of a layoutObject being | 286 // child so next is null. |
295 // inserted into the document's layout tree, all its former children coun ters are attached | 287 // 2. if the increment counter node lost it's root position as a result of a |
296 // to children of the inserted layoutObject and hence cannot be in scope for counter nodes | 288 // layoutObject being inserted into the document's layout tree, all its |
297 // attached to layoutObjects that were already in the document's layout t ree. | 289 // former children counters are attached to children of the inserted |
290 // layoutObject and hence cannot be in scope for counter nodes attached | |
291 // to layoutObjects that were already in the document's layout tree. | |
298 last->m_nextSibling = next; | 292 last->m_nextSibling = next; |
299 if (next) { | 293 if (next) { |
300 ASSERT(next->m_previousSibling == newChild); | 294 ASSERT(next->m_previousSibling == newChild); |
301 next->m_previousSibling = last; | 295 next->m_previousSibling = last; |
302 } else { | 296 } else { |
303 m_lastChild = last; | 297 m_lastChild = last; |
304 } | 298 } |
305 for (next = first;; next = next->m_nextSibling) { | 299 for (next = first;; next = next->m_nextSibling) { |
306 next->m_parent = this; | 300 next->m_parent = this; |
307 if (last == next) | 301 if (last == next) |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
374 #ifndef NDEBUG | 368 #ifndef NDEBUG |
375 | 369 |
376 void showCounterTree(const blink::CounterNode* counter) { | 370 void showCounterTree(const blink::CounterNode* counter) { |
377 if (counter) | 371 if (counter) |
378 showTreeAndMark(counter); | 372 showTreeAndMark(counter); |
379 else | 373 else |
380 fprintf(stderr, "Cannot showCounterTree for (nil).\n"); | 374 fprintf(stderr, "Cannot showCounterTree for (nil).\n"); |
381 } | 375 } |
382 | 376 |
383 #endif | 377 #endif |
OLD | NEW |