Chromium Code Reviews| 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 |