Changeset 77702 in webkit
- Timestamp:
- Feb 4, 2011 4:28:57 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r77700 r77702 1 2011-02-04 Carol Szabo <carol.szabo@nokia.com> 2 3 Reviewed by David Hyatt. 4 5 Code Changes. 6 7 CSS 2.1 failure: content-* 8 https://bugs.webkit.org/show_bug.cgi?id=52126 9 10 * fast/css/counters/content-021-expected.txt: Added. 11 * fast/css/counters/content-021.html: Added. 12 This is a copy of the test with the same name from the 13 official css test suite, adapted for DumpRenderTree. 14 1 15 2011-02-04 Dimitri Glazkov <dglazkov@chromium.org> 2 16 -
trunk/Source/WebCore/ChangeLog
r77698 r77702 1 2011-02-04 Carol Szabo <carol.szabo@nokia.com> 2 3 Reviewed by David Hyatt. 4 5 Code Changes. 6 7 CSS 2.1 failure: content-* 8 https://bugs.webkit.org/show_bug.cgi?id=52126 9 10 Test: fast/css/counters/content-021.html 11 12 * rendering/CounterNode.cpp: 13 (showCounterTree): 14 Made parameter const because it is supposed to be so. 15 * rendering/RenderCounter.cpp: 16 (WebCore::previousInPreOrder): 17 (WebCore::previousSiblingOrParent): 18 (WebCore::parentElement): 19 (WebCore::areRenderersElementsSiblings): 20 (WebCore::nextInPreOrder): 21 Added these local helper functions to help navigate the DOM tree 22 enriched with :before and :after pseudo elements. 23 (WebCore::planCounter): 24 Fixed bug that would create a repeat counter for second and 25 subsequent renderers associated with the same DOM element. 26 (WebCore::findPlaceForCounter): 27 (WebCore::makeCounterNode): 28 Changed to use the new tree navigation functions described above 29 instead of the Renderer Tree navigation functions. 30 (WebCore::RenderCounter::rendererSubtreeAttached): 31 (WebCore::RenderCounter::rendererStyleChanged): 32 Optimized to not bother about counters until the renderers are 33 finally attached. 34 (showRendererTree): 35 (showNodeTree): 36 Debug helper functions used to debug Counter bugs. 37 1 38 2011-02-04 Dan Bernstein <mitz@apple.com> 2 39 -
trunk/Source/WebCore/rendering/CounterNode.cpp
r75611 r77702 264 264 #ifndef NDEBUG 265 265 266 void show Tree(const WebCore::CounterNode* counter)266 void showCounterTree(const WebCore::CounterNode* counter) 267 267 { 268 268 if (counter) -
trunk/Source/WebCore/rendering/CounterNode.h
r68819 r77702 95 95 #ifndef NDEBUG 96 96 // Outside the WebCore namespace for ease of invocation from gdb. 97 void show Tree(const WebCore::CounterNode*);97 void showCounterTree(const WebCore::CounterNode*); 98 98 #endif 99 99 -
trunk/Source/WebCore/rendering/RenderCounter.cpp
r76859 r77702 25 25 #include "CounterNode.h" 26 26 #include "Document.h" 27 #include "Element.h" 27 28 #include "HTMLNames.h" 28 29 #include "HTMLOListElement.h" … … 47 48 } 48 49 49 static inline RenderObject* previousSiblingOrParent(RenderObject* object) 50 { 51 if (RenderObject* sibling = object->previousSibling()) 52 return sibling; 53 return object->parent(); 50 // This function processes the renderer tree in the order of the DOM tree 51 // including pseudo elements as defined in CSS 2.1. 52 // Anonymous renderers are skipped except for those representing pseudo elements. 53 static RenderObject* previousInPreOrder(const RenderObject* object) 54 { 55 Element* parent; 56 Element* sibling; 57 switch (object->style()->styleType()) { 58 case NOPSEUDO: 59 ASSERT(!object->isAnonymous()); 60 parent = toElement(object->node()); 61 sibling = parent->previousElementSibling(); 62 parent = parent->parentElement(); 63 break; 64 case BEFORE: 65 return object->generatingNode()->renderer(); // It is always the generating node's renderer 66 case AFTER: 67 parent = toElement(object->generatingNode()); 68 sibling = parent->lastElementChild(); 69 break; 70 default: 71 ASSERT_NOT_REACHED(); 72 return 0; 73 } 74 while (sibling) { 75 if (RenderObject* renderer = sibling->renderer()) { 76 if (RenderObject* after = renderer->afterPseudoElementRenderer()) 77 return after; 78 parent = sibling; 79 sibling = sibling->lastElementChild(); 80 if (!sibling) { 81 if (RenderObject* before = renderer->beforePseudoElementRenderer()) 82 return before; 83 return renderer; 84 } 85 } else 86 sibling = sibling->previousElementSibling(); 87 } 88 if (!parent) 89 return 0; 90 RenderObject* renderer = parent->renderer(); // Should never be null 91 if (RenderObject* before = renderer->beforePseudoElementRenderer()) 92 return before; 93 return renderer; 94 } 95 96 // This function processes the renderer tree in the order of the DOM tree 97 // including pseudo elements as defined in CSS 2.1. 98 // Anonymous renderers are skipped except for those representing pseudo elements. 99 static RenderObject* previousSiblingOrParent(const RenderObject* object) 100 { 101 Element* parent; 102 Element* sibling; 103 switch (object->style()->styleType()) { 104 case NOPSEUDO: 105 ASSERT(!object->isAnonymous()); 106 parent = toElement(object->node()); 107 sibling = parent->previousElementSibling(); 108 parent = parent->parentElement(); 109 break; 110 case BEFORE: 111 return object->generatingNode()->renderer(); // It is always the generating node's renderer 112 case AFTER: 113 parent = toElement(object->generatingNode()); 114 sibling = parent->lastElementChild(); 115 break; 116 default: 117 ASSERT_NOT_REACHED(); 118 return 0; 119 } 120 while (sibling) { 121 if (RenderObject* renderer = sibling->renderer()) // This skips invisible nodes 122 return renderer; 123 sibling = sibling->previousElementSibling(); 124 } 125 if (parent) { 126 RenderObject* renderer = parent->renderer(); 127 if (RenderObject* before = renderer->virtualChildren()->beforePseudoElementRenderer(renderer)) 128 return before; 129 return renderer; 130 } 131 return 0; 132 } 133 134 static Element* parentElement(RenderObject* object) 135 { 136 switch (object->style()->styleType()) { 137 case NOPSEUDO: 138 ASSERT(!object->isAnonymous()); 139 return toElement(object->node())->parentElement(); 140 case BEFORE: 141 case AFTER: 142 return toElement(object->generatingNode()); 143 default: 144 ASSERT_NOT_REACHED(); 145 return 0; 146 } 147 } 148 149 static inline bool areRenderersElementsSiblings(RenderObject* first, RenderObject* second) 150 { 151 return parentElement(first) == parentElement(second); 152 } 153 154 // This function processes the renderer tree in the order of the DOM tree 155 // including pseudo elements as defined in CSS 2.1. 156 // Anonymous renderers are skipped except for those representing pseudo elements. 157 static RenderObject* nextInPreOrder(const RenderObject* object, const Element* stayWithin, bool skipDescendants = false) 158 { 159 Element* self; 160 Element* child; 161 RenderObject* result; 162 self = toElement(object->generatingNode()); 163 if (skipDescendants) 164 goto nextsibling; 165 switch (object->style()->styleType()) { 166 case NOPSEUDO: 167 ASSERT(!object->isAnonymous()); 168 result = object->beforePseudoElementRenderer(); 169 if (result) 170 return result; 171 break; 172 case BEFORE: 173 break; 174 case AFTER: 175 goto nextsibling; 176 default: 177 ASSERT_NOT_REACHED(); 178 return 0; 179 } 180 child = self->firstElementChild(); 181 while (true) { 182 while (child) { 183 result = child->renderer(); 184 if (result) 185 return result; 186 child = child->nextElementSibling(); 187 } 188 result = self->renderer()->afterPseudoElementRenderer(); 189 if (result) 190 return result; 191 nextsibling: 192 if (self == stayWithin) 193 return 0; 194 child = self->nextElementSibling(); 195 self = self->parentElement(); 196 if (!self) { 197 ASSERT(!child); // We can only reach this if we are searching beyond the root element 198 return 0; // which cannot have siblings 199 } 200 } 54 201 } 55 202 … … 62 209 if (object->isText() && !object->isBR()) 63 210 return false; 64 211 Node* generatingNode = object->generatingNode(); 212 // We must have a generating node or else we cannot have a counter. 213 if (!generatingNode) 214 return false; 65 215 RenderStyle* style = object->style(); 66 216 ASSERT(style); 217 218 switch (style->styleType()) { 219 case NOPSEUDO: 220 // Sometimes nodes have more then one renderer. Only the first one gets the counter 221 // LayoutTests/http/tests/css/counter-crash.html 222 if (generatingNode->renderer() != object) 223 return false; 224 break; 225 case BEFORE: 226 case AFTER: 227 break; 228 default: 229 return false; // Counters are forbidden from all other pseudo elements. 230 } 67 231 68 232 if (const CounterDirectiveMap* directivesMap = style->counterDirectives()) { … … 134 298 // towards the begining of the document for counters with the same identifier as the one 135 299 // we are trying to find a place for. This is the next renderer to be checked. 136 RenderObject* currentRenderer = counterOwner->previousInPreOrder();300 RenderObject* currentRenderer = previousInPreOrder(counterOwner); 137 301 previousSibling = 0; 138 302 while (currentRenderer) { … … 145 309 if (currentCounter->actsAsReset()) { 146 310 // We found a reset counter that is on a renderer that is a sibling of ours or a parent. 147 if (isReset && currentRenderer->parent() == counterOwner->parent()) {311 if (isReset && areRenderersElementsSiblings(currentRenderer, counterOwner)) { 148 312 // We are also a reset counter and the previous reset was on a sibling renderer 149 313 // hence we are the next sibling of that counter if that reset is not a root or … … 160 324 } 161 325 // CurrentCounter, the counter at the EndSearchRenderer, is not reset. 162 if (!isReset || currentRenderer->parent() != counterOwner->parent()) {326 if (!isReset || !areRenderersElementsSiblings(currentRenderer, counterOwner)) { 163 327 // If the node we are placing is not reset or we have found a counter that is attached 164 328 // to an ancestor of the placed counter's renderer we know we are a sibling of that node. … … 173 337 // to currentCounter. 174 338 if (currentCounter->actsAsReset()) { 175 if (isReset && currentRenderer->parent() == counterOwner->parent()) {339 if (isReset && areRenderersElementsSiblings(currentRenderer, counterOwner)) { 176 340 parent = currentCounter->parent(); 177 341 previousSibling = currentCounter; … … 181 345 return true; 182 346 } 183 if (!isReset || currentRenderer->parent() != counterOwner->parent()) {347 if (!isReset || !areRenderersElementsSiblings(currentRenderer, counterOwner)) { 184 348 parent = currentCounter->parent(); 185 349 previousSibling = currentCounter; … … 206 370 // We are no longer interested in previous siblings of the currentRenderer or their children 207 371 // as counters they may have attached cannot be the previous sibling of the counter we are placing. 208 currentRenderer = currentRenderer->parent();372 currentRenderer = parentElement(currentRenderer)->renderer(); 209 373 continue; 210 374 } … … 257 421 } 258 422 nodeMap->set(identifier.impl(), newNode); 259 if (newNode->parent() || !object->nextInPreOrder(object->parent()))423 if (newNode->parent()) 260 424 return newNode.get(); 261 425 // Checking if some nodes that were previously counter tree root nodes 262 426 // should become children of this node now. 263 427 CounterMaps& maps = counterMaps(); 264 RenderObject* stayWithin = object->parent(); 265 for (RenderObject* currentRenderer = object->nextInPreOrder(stayWithin); currentRenderer; currentRenderer = currentRenderer->nextInPreOrder(stayWithin)) { 428 Element* stayWithin = parentElement(object); 429 bool skipDescendants; 430 for (RenderObject* currentRenderer = nextInPreOrder(object, stayWithin); currentRenderer; currentRenderer = nextInPreOrder(currentRenderer, stayWithin, skipDescendants)) { 431 skipDescendants = false; 266 432 if (!currentRenderer->m_hasCounterNodeMap) 267 433 continue; … … 269 435 if (!currentCounter) 270 436 continue; 437 skipDescendants = true; 271 438 if (currentCounter->parent()) { 272 439 ASSERT(newNode->firstChild()); 273 if (currentRenderer->lastChild())274 currentRenderer = currentRenderer->lastChild();275 440 continue; 276 441 } 277 if (stayWithin != currentRenderer->parent() || !currentCounter->hasResetType()) 278 newNode->insertAfter(currentCounter, newNode->lastChild(), identifier); 279 if (currentRenderer->lastChild()) 280 currentRenderer = currentRenderer->lastChild(); 442 if (stayWithin == parentElement(currentRenderer) && currentCounter->hasResetType()) 443 break; 444 newNode->insertAfter(currentCounter, newNode->lastChild(), identifier); 281 445 } 282 446 return newNode.get(); … … 445 609 void RenderCounter::rendererSubtreeAttached(RenderObject* renderer) 446 610 { 611 Node* node = renderer->node(); 612 if (node) 613 node = node->parentNode(); 614 else 615 node = renderer->generatingNode(); 616 if (node && !node->attached()) 617 return; // No need to update if the parent is not attached yet 447 618 for (RenderObject* descendant = renderer; descendant; descendant = descendant->nextInPreOrder(renderer)) 448 619 updateCounters(descendant); … … 451 622 void RenderCounter::rendererStyleChanged(RenderObject* renderer, const RenderStyle* oldStyle, const RenderStyle* newStyle) 452 623 { 624 Node* node = renderer->generatingNode(); 625 if (!node || !node->attached()) 626 return; // cannot have generated content or if it can have, it will be handled during attaching 453 627 const CounterDirectiveMap* newCounterDirectives; 454 628 const CounterDirectiveMap* oldCounterDirectives; … … 490 664 491 665 } // namespace WebCore 666 667 #ifndef NDEBUG 668 669 void showCounterRendererTree(const WebCore::RenderObject* renderer, const char* counterName) 670 { 671 if (!renderer) 672 return; 673 const WebCore::RenderObject* root = renderer; 674 while (root->parent()) 675 root = root->parent(); 676 677 AtomicString identifier(counterName); 678 for (const WebCore::RenderObject* current = root; current; current = current->nextInPreOrder()) { 679 fprintf(stderr, "%c", (current == renderer) ? '*' : ' '); 680 for (const WebCore::RenderObject* parent = current; parent && parent != root; parent = parent->parent()) 681 fprintf(stderr, " "); 682 fprintf(stderr, "%p N:%p P:%p PS:%p NS:%p C:%p\n", 683 current, current->node(), current->parent(), current->previousSibling(), 684 current->nextSibling(), current->m_hasCounterNodeMap? 685 counterName ? WebCore::counterMaps().get(current)->get(identifier.impl()).get() : (WebCore::CounterNode*)1 : (WebCore::CounterNode*)0); 686 } 687 } 688 689 #endif // NDEBUG -
trunk/Source/WebCore/rendering/RenderCounter.h
r69437 r77702 68 68 } // namespace WebCore 69 69 70 #ifndef NDEBUG 71 // Outside the WebCore namespace for ease of invocation from gdb. 72 void showCounterRendererTree(const WebCore::RenderObject*, const char* counterName = 0); 73 #endif 74 70 75 #endif // RenderCounter_h
Note: See TracChangeset
for help on using the changeset viewer.