Changeset 53355 in webkit
- Timestamp:
- Jan 15, 2010 6:14:25 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r53352 r53355 1 2010-01-15 Carol Szabo <carol.szabo@nokia.com> 2 3 Reviewed by Darin Adler. 4 5 CSS2.1 Counters not updated when new elements are inserted in the DOM. 6 https://bugs.webkit.org/show_bug.cgi?id=32884 7 8 * fast/css/counters/adding-nodes-expected.txt: Added. 9 * fast/css/counters/adding-nodes.html: Added. 10 1 11 2010-01-15 Darin Fisher <darin@chromium.org> 2 12 -
trunk/WebCore/ChangeLog
r53351 r53355 1 2010-01-15 Carol Szabo <carol.szabo@nokia.com> 2 3 Reviewed by Darin Adler. 4 5 CSS2.1 Counters not updated when new elements are inserted in the DOM. 6 https://bugs.webkit.org/show_bug.cgi?id=32884 7 8 Test: fast/css/counters/adding-nodes.html 9 10 * rendering/CounterNode.cpp: 11 (WebCore::CounterNode::insertAfter): 12 Modified to handle the addition of nodes with children. Needed when formerly 13 root nodes become descendants of a new node. 14 * rendering/RenderCounter.cpp: 15 (WebCore::makeCounterNode): 16 Changed to handle the case when root counter nodes lose their root 17 status as a result of a new root counter node creation. 18 (WebCore::destroyCounterNodeWithoutMapRemoval): 19 Refactored more code into destroyCounterNodeChildren and renamed the 20 function according to its new action. 21 (WebCore::RenderCounter::destroyCounterNodes): 22 Simplified to share more code with the new destroyCounterNode. 23 (WebCore::RenderCounter::destroyCounterNode): 24 Added to allow for selective counterNode destruction. 25 (WebCore::RenderCounter::rendererSubtreeAttached): 26 Added to refresh counter values in response to DOM changes. 27 For renderers with no attached counters the execution time of this 28 function cannot be discerned in comparison with the time needed to 29 add a node or change the style of a node. 30 (WebCore::updateCounters): 31 Helper function for rendererSubtreeAttached. Updates the counters 32 attached to a Renderer in response to the renderer or its ancestors 33 being attached to the renderer tree. 34 * rendering/RenderCounter.h: 35 * rendering/RenderObject.cpp: 36 (WebCore::RenderObject::addChild): 37 Changed to update counter values if needed. 38 1 39 2010-01-15 Alejandro G. Castro <alex@igalia.com> 2 40 -
trunk/WebCore/rendering/CounterNode.cpp
r53230 r53355 23 23 #include "CounterNode.h" 24 24 25 #include "RenderCounter.h" 25 26 #include "RenderObject.h" 26 27 #include <stdio.h> 27 28 // FIXME: There's currently no strategy for getting the counter tree updated when new29 // 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 a31 // "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 and33 // t1204-reset tests in the CSS 2.1 test suite.34 28 35 29 namespace WebCore { … … 141 135 ASSERT(!refChild || refChild->m_parent == this); 142 136 137 if (newChild->m_hasResetType) { 138 while (m_lastChild != refChild) 139 RenderCounter::destroyCounterNode(m_lastChild->renderer(), identifier); 140 } 141 143 142 CounterNode* next; 144 143 … … 151 150 } 152 151 153 if (next) {154 ASSERT(next->m_previousSibling == refChild);155 next->m_previousSibling = newChild;156 } else {157 ASSERT(m_lastChild == refChild);158 m_lastChild = newChild;159 }160 161 152 newChild->m_parent = this; 162 153 newChild->m_previousSibling = refChild; 163 newChild->m_nextSibling = next; 164 154 155 if (!newChild->m_firstChild || newChild->m_hasResetType) { 156 newChild->m_nextSibling = next; 157 if (next) { 158 ASSERT(next->m_previousSibling == refChild); 159 next->m_previousSibling = newChild; 160 } else { 161 ASSERT(m_lastChild == refChild); 162 m_lastChild = newChild; 163 } 164 165 newChild->m_countInParent = newChild->computeCountInParent(); 166 newChild->resetRenderers(identifier); 167 if (next) 168 next->recount(identifier); 169 return; 170 } 171 172 // The code below handles the case when a formerly root increment counter is loosing its root position 173 // and therefore its children become next siblings. 174 CounterNode* last = newChild->m_lastChild; 175 CounterNode* first = newChild->m_firstChild; 176 177 newChild->m_nextSibling = first; 178 first->m_previousSibling = newChild; 179 // The case when the original next sibling of the inserted node becomes a child of 180 // one of the former children of the inserted node is not handled as it is believed 181 // to be impossible since: 182 // 1. if the increment counter node lost it's root position as a result of another 183 // counter node being created, it will be inserted as the last child so next is null. 184 // 2. if the increment counter node lost it's root position as a result of a renderer being 185 // inserted into the document's render tree, all its former children counters are attached 186 // to children of the inserted renderer and hence cannot be in scope for counter nodes 187 // attached to renderers that were already in the document's render tree. 188 last->m_nextSibling = next; 189 if (next) 190 next->m_previousSibling = last; 191 else 192 m_lastChild = last; 193 for (next = first; ; next = next->m_nextSibling) { 194 next->m_parent = this; 195 if (last == next) 196 break; 197 } 198 newChild->m_firstChild = 0; 199 newChild->m_lastChild = 0; 165 200 newChild->m_countInParent = newChild->computeCountInParent(); 166 if (next)167 next->recount(identifier);201 newChild->resetRenderer(identifier); 202 first->recount(identifier); 168 203 } 169 204 -
trunk/WebCore/rendering/RenderCounter.cpp
r52450 r53355 255 255 } 256 256 nodeMap->set(identifier.impl(), newNode); 257 if (newNode->parent() || !object->nextInPreOrder(object->parent())) 258 return newNode; 259 // Checking if some nodes that were previously counter tree root nodes 260 // should become children of this node now. 261 CounterMaps& maps = counterMaps(); 262 RenderObject* stayWithin = object->parent(); 263 for (RenderObject* currentRenderer = object->nextInPreOrder(stayWithin); currentRenderer; currentRenderer = currentRenderer->nextInPreOrder(stayWithin)) { 264 if (!currentRenderer->m_hasCounterNodeMap) 265 continue; 266 CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier.impl()); 267 if (!currentCounter) 268 continue; 269 if (currentCounter->parent()) { 270 ASSERT(newNode->firstChild()); 271 if (currentRenderer->lastChild()) 272 currentRenderer = currentRenderer->lastChild(); 273 continue; 274 } 275 if (stayWithin != currentRenderer->parent() || !currentCounter->hasResetType()) 276 newNode->insertAfter(currentCounter, newNode->lastChild(), identifier); 277 if (currentRenderer->lastChild()) 278 currentRenderer = currentRenderer->lastChild(); 279 } 257 280 return newNode; 258 281 } … … 315 338 } 316 339 317 static void destroyCounterNode Children(const AtomicString& identifier, CounterNode* node)340 static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, CounterNode* node) 318 341 { 319 342 CounterNode* previous; … … 330 353 delete child; 331 354 } 332 } 333 334 void RenderCounter::destroyCounterNodes(RenderObject* object) 355 RenderObject* renderer = node->renderer(); 356 if (!renderer->documentBeingDestroyed()) { 357 if (RenderObjectChildList* children = renderer->virtualChildren()) 358 children->invalidateCounters(renderer, identifier); 359 } 360 if (CounterNode* parent = node->parent()) 361 parent->removeChild(node, identifier); 362 delete node; 363 } 364 365 void RenderCounter::destroyCounterNodes(RenderObject* renderer) 335 366 { 336 367 CounterMaps& maps = counterMaps(); 337 CounterMap* map = maps.get(object); 338 if (!map) 339 return; 340 maps.remove(object); 341 368 CounterMaps::iterator mapsIterator = maps.find(renderer); 369 if (mapsIterator == maps.end()) 370 return; 371 CounterMap* map = mapsIterator->second; 342 372 CounterMap::const_iterator end = map->end(); 343 373 for (CounterMap::const_iterator it = map->begin(); it != end; ++it) { 344 CounterNode* node = it->second;345 374 AtomicString identifier(it->first.get()); 346 destroyCounterNodeChildren(identifier, node); 347 if (CounterNode* parent = node->parent()) 348 parent->removeChild(node, identifier); 349 delete node; 350 } 351 375 destroyCounterNodeWithoutMapRemoval(identifier, it->second); 376 } 377 maps.remove(mapsIterator); 352 378 delete map; 379 renderer->m_hasCounterNodeMap = false; 380 } 381 382 void RenderCounter::destroyCounterNode(RenderObject* renderer, const AtomicString& identifier) 383 { 384 CounterMap* map = counterMaps().get(renderer); 385 if (!map) 386 return; 387 CounterMap::iterator mapIterator = map->find(identifier.impl()); 388 if (mapIterator == map->end()) 389 return; 390 destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->second); 391 map->remove(mapIterator); 392 // We do not delete "map" here even if empty because we expect to reuse 393 // it soon. In order for a renderer to lose all its counters permanently, 394 // a style change for the renderer involving removal of all counter 395 // directives must occur, in which case, RenderCounter::destroyCounterNodes() 396 // must be called. 397 // The destruction of the Renderer (possibly caused by the removal of its 398 // associated DOM node) is the other case that leads to the permanent 399 // destruction of all counters attached to a Renderer. In this case 400 // RenderCounter::destroyCounterNodes() must be and is now called, too. 401 // RenderCounter::destroyCounterNodes() handles destruction of the counter 402 // map associated with a renderer, so there is no risk in leaking the map. 403 } 404 405 static void updateCounters(RenderObject* renderer) 406 { 407 ASSERT(renderer->style()); 408 const CounterDirectiveMap* directiveMap = renderer->style()->counterDirectives(); 409 if (!directiveMap) 410 return; 411 CounterDirectiveMap::const_iterator end = directiveMap->end(); 412 if (!renderer->m_hasCounterNodeMap) { 413 for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) 414 makeCounterNode(renderer, AtomicString(it->first.get()), false); 415 return; 416 } 417 CounterMap* counterMap = counterMaps().get(renderer); 418 ASSERT(counterMap); 419 for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) { 420 CounterNode* node = counterMap->get(it->first.get()); 421 if (!node) { 422 makeCounterNode(renderer, AtomicString(it->first.get()), false); 423 continue; 424 } 425 CounterNode* newParent = 0; 426 CounterNode* newPreviousSibling; 427 findPlaceForCounter(renderer, AtomicString(it->first.get()), node->hasResetType(), newParent, newPreviousSibling); 428 CounterNode* parent = node->parent(); 429 if (newParent == parent && newPreviousSibling == node->previousSibling()) 430 continue; 431 if (parent) 432 parent->removeChild(node, it->first.get()); 433 newParent->insertAfter(node, newPreviousSibling, it->first.get()); 434 } 435 } 436 437 void RenderCounter::rendererSubtreeAttached(RenderObject* renderer) 438 { 439 for (RenderObject* descendant = renderer; descendant; descendant = descendant->nextInPreOrder(renderer)) 440 updateCounters(descendant); 353 441 } 354 442 -
trunk/WebCore/rendering/RenderCounter.h
r50960 r53355 41 41 42 42 static void destroyCounterNodes(RenderObject*); 43 static void destroyCounterNode(RenderObject*, const AtomicString& identifier); 44 static void rendererSubtreeAttached(RenderObject*); 43 45 44 46 private: -
trunk/WebCore/rendering/RenderObject.cpp
r53196 r53355 310 310 children->insertChildNode(this, newChild, beforeChild); 311 311 } 312 312 RenderCounter::rendererSubtreeAttached(newChild); 313 313 if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) { 314 314 RefPtr<StringImpl> textToTransform = toRenderText(newChild)->originalText();
Note: See TracChangeset
for help on using the changeset viewer.