| OLD | NEW |
| 1 /** | 1 /** |
| 2 * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) | 2 * Copyright (C) 2004 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 return nullptr; | 66 return nullptr; |
| 67 } | 67 } |
| 68 | 68 |
| 69 // This function processes the layoutObject tree in the order of the DOM tree | 69 // This function processes the layoutObject tree in the order of the DOM tree |
| 70 // including pseudo elements as defined in CSS 2.1. This method will always | 70 // including pseudo elements as defined in CSS 2.1. This method will always |
| 71 // return either a previous object within the same contain: style scope or | 71 // return either a previous object within the same contain: style scope or |
| 72 // nullptr. | 72 // nullptr. |
| 73 static LayoutObject* previousInPreOrderRespectingContainment( | 73 static LayoutObject* previousInPreOrderRespectingContainment( |
| 74 const LayoutObject& object) { | 74 const LayoutObject& object) { |
| 75 Element* self = toElement(object.node()); | 75 Element* self = toElement(object.node()); |
| 76 ASSERT(self); | 76 DCHECK(self); |
| 77 Element* previous = ElementTraversal::previousIncludingPseudo(*self); | 77 Element* previous = ElementTraversal::previousIncludingPseudo(*self); |
| 78 Element* styleContainAncestor = ancestorStyleContainmentObject(*self); | 78 Element* styleContainAncestor = ancestorStyleContainmentObject(*self); |
| 79 | 79 |
| 80 while (1) { | 80 while (1) { |
| 81 while (previous && !previous->layoutObject()) | 81 while (previous && !previous->layoutObject()) |
| 82 previous = ElementTraversal::previousIncludingPseudo(*previous); | 82 previous = ElementTraversal::previousIncludingPseudo(*previous); |
| 83 if (!previous) | 83 if (!previous) |
| 84 return nullptr; | 84 return nullptr; |
| 85 Element* previousStyleContainAncestor = | 85 Element* previousStyleContainAncestor = |
| 86 ancestorStyleContainmentObject(*previous); | 86 ancestorStyleContainmentObject(*previous); |
| 87 if (previousStyleContainAncestor == styleContainAncestor) | 87 if (previousStyleContainAncestor == styleContainAncestor) |
| 88 return previous->layoutObject(); | 88 return previous->layoutObject(); |
| 89 if (!previousStyleContainAncestor) | 89 if (!previousStyleContainAncestor) |
| 90 return nullptr; | 90 return nullptr; |
| 91 previous = previousStyleContainAncestor; | 91 previous = previousStyleContainAncestor; |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 // This function processes the layoutObject tree in the order of the DOM tree | 95 // This function processes the layoutObject tree in the order of the DOM tree |
| 96 // including pseudo elements as defined in CSS 2.1. This method avoids crossing | 96 // including pseudo elements as defined in CSS 2.1. This method avoids crossing |
| 97 // contain: style boundaries. | 97 // contain: style boundaries. |
| 98 static LayoutObject* previousSiblingOrParentRespectingContainment( | 98 static LayoutObject* previousSiblingOrParentRespectingContainment( |
| 99 const LayoutObject& object) { | 99 const LayoutObject& object) { |
| 100 Element* self = toElement(object.node()); | 100 Element* self = toElement(object.node()); |
| 101 ASSERT(self); | 101 DCHECK(self); |
| 102 Element* previous = ElementTraversal::pseudoAwarePreviousSibling(*self); | 102 Element* previous = ElementTraversal::pseudoAwarePreviousSibling(*self); |
| 103 while (previous && !previous->layoutObject()) | 103 while (previous && !previous->layoutObject()) |
| 104 previous = ElementTraversal::pseudoAwarePreviousSibling(*previous); | 104 previous = ElementTraversal::pseudoAwarePreviousSibling(*previous); |
| 105 if (previous) | 105 if (previous) |
| 106 return previous->layoutObject(); | 106 return previous->layoutObject(); |
| 107 previous = self->parentElement(); | 107 previous = self->parentElement(); |
| 108 return previous && previous->layoutObject() && | 108 return previous && previous->layoutObject() && |
| 109 !(previous->layoutObject()->style()->contain() & ContainsStyle) | 109 !(previous->layoutObject()->style()->contain() & ContainsStyle) |
| 110 ? previous->layoutObject() | 110 ? previous->layoutObject() |
| 111 : nullptr; | 111 : nullptr; |
| 112 } | 112 } |
| 113 | 113 |
| 114 static inline Element* parentElement(LayoutObject& object) { | 114 static inline Element* parentElement(LayoutObject& object) { |
| 115 return toElement(object.node())->parentElement(); | 115 return toElement(object.node())->parentElement(); |
| 116 } | 116 } |
| 117 | 117 |
| 118 static inline bool areLayoutObjectsElementsSiblings(LayoutObject& first, | 118 static inline bool areLayoutObjectsElementsSiblings(LayoutObject& first, |
| 119 LayoutObject& second) { | 119 LayoutObject& second) { |
| 120 return parentElement(first) == parentElement(second); | 120 return parentElement(first) == parentElement(second); |
| 121 } | 121 } |
| 122 | 122 |
| 123 // This function processes the layoutObject tree in the order of the DOM tree | 123 // This function processes the layoutObject tree in the order of the DOM tree |
| 124 // including pseudo elements as defined in CSS 2.1. | 124 // including pseudo elements as defined in CSS 2.1. |
| 125 static LayoutObject* nextInPreOrder(const LayoutObject& object, | 125 static LayoutObject* nextInPreOrder(const LayoutObject& object, |
| 126 const Element* stayWithin, | 126 const Element* stayWithin, |
| 127 bool skipDescendants = false) { | 127 bool skipDescendants = false) { |
| 128 Element* self = toElement(object.node()); | 128 Element* self = toElement(object.node()); |
| 129 ASSERT(self); | 129 DCHECK(self); |
| 130 Element* next = | 130 Element* next = |
| 131 skipDescendants | 131 skipDescendants |
| 132 ? ElementTraversal::nextIncludingPseudoSkippingChildren(*self, | 132 ? ElementTraversal::nextIncludingPseudoSkippingChildren(*self, |
| 133 stayWithin) | 133 stayWithin) |
| 134 : ElementTraversal::nextIncludingPseudo(*self, stayWithin); | 134 : ElementTraversal::nextIncludingPseudo(*self, stayWithin); |
| 135 while (next && !next->layoutObject()) | 135 while (next && !next->layoutObject()) |
| 136 next = skipDescendants | 136 next = skipDescendants |
| 137 ? ElementTraversal::nextIncludingPseudoSkippingChildren( | 137 ? ElementTraversal::nextIncludingPseudoSkippingChildren( |
| 138 *next, stayWithin) | 138 *next, stayWithin) |
| 139 : ElementTraversal::nextIncludingPseudo(*next, stayWithin); | 139 : ElementTraversal::nextIncludingPseudo(*next, stayWithin); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 m_nextForSameCounter(nullptr) { | 433 m_nextForSameCounter(nullptr) { |
| 434 setDocumentForAnonymous(&pseudo.document()); | 434 setDocumentForAnonymous(&pseudo.document()); |
| 435 view()->addLayoutCounter(); | 435 view()->addLayoutCounter(); |
| 436 } | 436 } |
| 437 | 437 |
| 438 LayoutCounter::~LayoutCounter() {} | 438 LayoutCounter::~LayoutCounter() {} |
| 439 | 439 |
| 440 void LayoutCounter::willBeDestroyed() { | 440 void LayoutCounter::willBeDestroyed() { |
| 441 if (m_counterNode) { | 441 if (m_counterNode) { |
| 442 m_counterNode->removeLayoutObject(this); | 442 m_counterNode->removeLayoutObject(this); |
| 443 ASSERT(!m_counterNode); | 443 DCHECK(!m_counterNode); |
| 444 } | 444 } |
| 445 if (view()) | 445 if (view()) |
| 446 view()->removeLayoutCounter(); | 446 view()->removeLayoutCounter(); |
| 447 LayoutText::willBeDestroyed(); | 447 LayoutText::willBeDestroyed(); |
| 448 } | 448 } |
| 449 | 449 |
| 450 PassRefPtr<StringImpl> LayoutCounter::originalText() const { | 450 PassRefPtr<StringImpl> LayoutCounter::originalText() const { |
| 451 if (!m_counterNode) { | 451 if (!m_counterNode) { |
| 452 LayoutObject* beforeAfterContainer = parent(); | 452 LayoutObject* beforeAfterContainer = parent(); |
| 453 while (true) { | 453 while (true) { |
| 454 if (!beforeAfterContainer) | 454 if (!beforeAfterContainer) |
| 455 return nullptr; | 455 return nullptr; |
| 456 if (!beforeAfterContainer->isAnonymous() && | 456 if (!beforeAfterContainer->isAnonymous() && |
| 457 !beforeAfterContainer->isPseudoElement()) | 457 !beforeAfterContainer->isPseudoElement()) |
| 458 return nullptr; // LayoutCounters are restricted to before and after | 458 return nullptr; // LayoutCounters are restricted to before and after |
| 459 // pseudo elements | 459 // pseudo elements |
| 460 PseudoId containerStyle = beforeAfterContainer->style()->styleType(); | 460 PseudoId containerStyle = beforeAfterContainer->style()->styleType(); |
| 461 if ((containerStyle == PseudoIdBefore) || | 461 if ((containerStyle == PseudoIdBefore) || |
| 462 (containerStyle == PseudoIdAfter)) | 462 (containerStyle == PseudoIdAfter)) |
| 463 break; | 463 break; |
| 464 beforeAfterContainer = beforeAfterContainer->parent(); | 464 beforeAfterContainer = beforeAfterContainer->parent(); |
| 465 } | 465 } |
| 466 makeCounterNodeIfNeeded(*beforeAfterContainer, m_counter.identifier(), true) | 466 makeCounterNodeIfNeeded(*beforeAfterContainer, m_counter.identifier(), true) |
| 467 ->addLayoutObject(const_cast<LayoutCounter*>(this)); | 467 ->addLayoutObject(const_cast<LayoutCounter*>(this)); |
| 468 ASSERT(m_counterNode); | 468 DCHECK(m_counterNode); |
| 469 } | 469 } |
| 470 CounterNode* child = m_counterNode; | 470 CounterNode* child = m_counterNode; |
| 471 int value = child->actsAsReset() ? child->value() : child->countInParent(); | 471 int value = child->actsAsReset() ? child->value() : child->countInParent(); |
| 472 | 472 |
| 473 String text = ListMarkerText::text(m_counter.listStyle(), value); | 473 String text = ListMarkerText::text(m_counter.listStyle(), value); |
| 474 | 474 |
| 475 if (!m_counter.separator().isNull()) { | 475 if (!m_counter.separator().isNull()) { |
| 476 if (!child->actsAsReset()) | 476 if (!child->actsAsReset()) |
| 477 child = child->parent(); | 477 child = child->parent(); |
| 478 while (CounterNode* parent = child->parent()) { | 478 while (CounterNode* parent = child->parent()) { |
| 479 text = | 479 text = |
| 480 ListMarkerText::text(m_counter.listStyle(), child->countInParent()) + | 480 ListMarkerText::text(m_counter.listStyle(), child->countInParent()) + |
| 481 m_counter.separator() + text; | 481 m_counter.separator() + text; |
| 482 child = parent; | 482 child = parent; |
| 483 } | 483 } |
| 484 } | 484 } |
| 485 | 485 |
| 486 return text.impl(); | 486 return text.impl(); |
| 487 } | 487 } |
| 488 | 488 |
| 489 void LayoutCounter::updateCounter() { | 489 void LayoutCounter::updateCounter() { |
| 490 setText(originalText()); | 490 setText(originalText()); |
| 491 } | 491 } |
| 492 | 492 |
| 493 void LayoutCounter::invalidate() { | 493 void LayoutCounter::invalidate() { |
| 494 m_counterNode->removeLayoutObject(this); | 494 m_counterNode->removeLayoutObject(this); |
| 495 ASSERT(!m_counterNode); | 495 DCHECK(!m_counterNode); |
| 496 if (documentBeingDestroyed()) | 496 if (documentBeingDestroyed()) |
| 497 return; | 497 return; |
| 498 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 498 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
| 499 LayoutInvalidationReason::CountersChanged); | 499 LayoutInvalidationReason::CountersChanged); |
| 500 } | 500 } |
| 501 | 501 |
| 502 static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, | 502 static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, |
| 503 CounterNode* node) { | 503 CounterNode* node) { |
| 504 CounterNode* previous; | 504 CounterNode* previous; |
| 505 for (RefPtr<CounterNode> child = node->lastDescendant(); | 505 for (RefPtr<CounterNode> child = node->lastDescendant(); |
| 506 child && child != node; child = previous) { | 506 child && child != node; child = previous) { |
| 507 previous = child->previousInPreOrder(); | 507 previous = child->previousInPreOrder(); |
| 508 child->parent()->removeChild(child.get()); | 508 child->parent()->removeChild(child.get()); |
| 509 ASSERT(counterMaps().at(&child->owner())->at(identifier) == child); | 509 DCHECK(counterMaps().at(&child->owner())->at(identifier) == child); |
| 510 counterMaps().at(&child->owner())->erase(identifier); | 510 counterMaps().at(&child->owner())->erase(identifier); |
| 511 } | 511 } |
| 512 if (CounterNode* parent = node->parent()) | 512 if (CounterNode* parent = node->parent()) |
| 513 parent->removeChild(node); | 513 parent->removeChild(node); |
| 514 } | 514 } |
| 515 | 515 |
| 516 void LayoutCounter::destroyCounterNodes(LayoutObject& owner) { | 516 void LayoutCounter::destroyCounterNodes(LayoutObject& owner) { |
| 517 CounterMaps& maps = counterMaps(); | 517 CounterMaps& maps = counterMaps(); |
| 518 CounterMaps::iterator mapsIterator = maps.find(&owner); | 518 CounterMaps::iterator mapsIterator = maps.find(&owner); |
| 519 if (mapsIterator == maps.end()) | 519 if (mapsIterator == maps.end()) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 545 // The destruction of the LayoutObject (possibly caused by the removal of its | 545 // The destruction of the LayoutObject (possibly caused by the removal of its |
| 546 // associated DOM node) is the other case that leads to the permanent | 546 // associated DOM node) is the other case that leads to the permanent |
| 547 // destruction of all counters attached to a LayoutObject. In this case | 547 // destruction of all counters attached to a LayoutObject. In this case |
| 548 // LayoutCounter::destroyCounterNodes() must be and is now called, too. | 548 // LayoutCounter::destroyCounterNodes() must be and is now called, too. |
| 549 // LayoutCounter::destroyCounterNodes() handles destruction of the counter | 549 // LayoutCounter::destroyCounterNodes() handles destruction of the counter |
| 550 // map associated with a layoutObject, so there is no risk in leaking the map. | 550 // map associated with a layoutObject, so there is no risk in leaking the map. |
| 551 } | 551 } |
| 552 | 552 |
| 553 void LayoutCounter::layoutObjectSubtreeWillBeDetached( | 553 void LayoutCounter::layoutObjectSubtreeWillBeDetached( |
| 554 LayoutObject* layoutObject) { | 554 LayoutObject* layoutObject) { |
| 555 ASSERT(layoutObject->view()); | 555 DCHECK(layoutObject->view()); |
| 556 // View should never be non-zero. crbug.com/546939 | 556 // View should never be non-zero. crbug.com/546939 |
| 557 if (!layoutObject->view() || !layoutObject->view()->hasLayoutCounters()) | 557 if (!layoutObject->view() || !layoutObject->view()->hasLayoutCounters()) |
| 558 return; | 558 return; |
| 559 | 559 |
| 560 LayoutObject* currentLayoutObject = layoutObject->lastLeafChild(); | 560 LayoutObject* currentLayoutObject = layoutObject->lastLeafChild(); |
| 561 if (!currentLayoutObject) | 561 if (!currentLayoutObject) |
| 562 currentLayoutObject = layoutObject; | 562 currentLayoutObject = layoutObject; |
| 563 while (true) { | 563 while (true) { |
| 564 destroyCounterNodes(*currentLayoutObject); | 564 destroyCounterNodes(*currentLayoutObject); |
| 565 if (currentLayoutObject == layoutObject) | 565 if (currentLayoutObject == layoutObject) |
| 566 break; | 566 break; |
| 567 currentLayoutObject = currentLayoutObject->previousInPreOrder(); | 567 currentLayoutObject = currentLayoutObject->previousInPreOrder(); |
| 568 } | 568 } |
| 569 } | 569 } |
| 570 | 570 |
| 571 static void updateCounters(LayoutObject& layoutObject) { | 571 static void updateCounters(LayoutObject& layoutObject) { |
| 572 ASSERT(layoutObject.style()); | 572 DCHECK(layoutObject.style()); |
| 573 const CounterDirectiveMap* directiveMap = | 573 const CounterDirectiveMap* directiveMap = |
| 574 layoutObject.style()->counterDirectives(); | 574 layoutObject.style()->counterDirectives(); |
| 575 if (!directiveMap) | 575 if (!directiveMap) |
| 576 return; | 576 return; |
| 577 CounterDirectiveMap::const_iterator end = directiveMap->end(); | 577 CounterDirectiveMap::const_iterator end = directiveMap->end(); |
| 578 if (!layoutObject.hasCounterNodeMap()) { | 578 if (!layoutObject.hasCounterNodeMap()) { |
| 579 for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); | 579 for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); |
| 580 it != end; ++it) | 580 it != end; ++it) |
| 581 makeCounterNodeIfNeeded(layoutObject, it->key, false); | 581 makeCounterNodeIfNeeded(layoutObject, it->key, false); |
| 582 return; | 582 return; |
| 583 } | 583 } |
| 584 CounterMap* counterMap = counterMaps().at(&layoutObject); | 584 CounterMap* counterMap = counterMaps().at(&layoutObject); |
| 585 ASSERT(counterMap); | 585 DCHECK(counterMap); |
| 586 for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); | 586 for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); |
| 587 it != end; ++it) { | 587 it != end; ++it) { |
| 588 RefPtr<CounterNode> node = counterMap->at(it->key); | 588 RefPtr<CounterNode> node = counterMap->at(it->key); |
| 589 if (!node) { | 589 if (!node) { |
| 590 makeCounterNodeIfNeeded(layoutObject, it->key, false); | 590 makeCounterNodeIfNeeded(layoutObject, it->key, false); |
| 591 continue; | 591 continue; |
| 592 } | 592 } |
| 593 RefPtr<CounterNode> newParent = nullptr; | 593 RefPtr<CounterNode> newParent = nullptr; |
| 594 RefPtr<CounterNode> newPreviousSibling = nullptr; | 594 RefPtr<CounterNode> newPreviousSibling = nullptr; |
| 595 | 595 |
| 596 findPlaceForCounter(layoutObject, it->key, node->hasResetType(), newParent, | 596 findPlaceForCounter(layoutObject, it->key, node->hasResetType(), newParent, |
| 597 newPreviousSibling); | 597 newPreviousSibling); |
| 598 if (node != counterMap->at(it->key)) | 598 if (node != counterMap->at(it->key)) |
| 599 continue; | 599 continue; |
| 600 CounterNode* parent = node->parent(); | 600 CounterNode* parent = node->parent(); |
| 601 if (newParent == parent && newPreviousSibling == node->previousSibling()) | 601 if (newParent == parent && newPreviousSibling == node->previousSibling()) |
| 602 continue; | 602 continue; |
| 603 if (parent) | 603 if (parent) |
| 604 parent->removeChild(node.get()); | 604 parent->removeChild(node.get()); |
| 605 if (newParent) | 605 if (newParent) |
| 606 newParent->insertAfter(node.get(), newPreviousSibling.get(), it->key); | 606 newParent->insertAfter(node.get(), newPreviousSibling.get(), it->key); |
| 607 } | 607 } |
| 608 } | 608 } |
| 609 | 609 |
| 610 void LayoutCounter::layoutObjectSubtreeAttached(LayoutObject* layoutObject) { | 610 void LayoutCounter::layoutObjectSubtreeAttached(LayoutObject* layoutObject) { |
| 611 ASSERT(layoutObject->view()); | 611 DCHECK(layoutObject->view()); |
| 612 if (!layoutObject->view()->hasLayoutCounters()) | 612 if (!layoutObject->view()->hasLayoutCounters()) |
| 613 return; | 613 return; |
| 614 Node* node = layoutObject->node(); | 614 Node* node = layoutObject->node(); |
| 615 if (node) | 615 if (node) |
| 616 node = node->parentNode(); | 616 node = node->parentNode(); |
| 617 else | 617 else |
| 618 node = layoutObject->generatingNode(); | 618 node = layoutObject->generatingNode(); |
| 619 if (node && node->needsAttach()) | 619 if (node && node->needsAttach()) |
| 620 return; // No need to update if the parent is not attached yet | 620 return; // No need to update if the parent is not attached yet |
| 621 for (LayoutObject* descendant = layoutObject; descendant; | 621 for (LayoutObject* descendant = layoutObject; descendant; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 current->nextSibling(), | 707 current->nextSibling(), |
| 708 current->hasCounterNodeMap() | 708 current->hasCounterNodeMap() |
| 709 ? counterName ? blink::counterMaps().at(current)->at(identifier) | 709 ? counterName ? blink::counterMaps().at(current)->at(identifier) |
| 710 : (blink::CounterNode*)1 | 710 : (blink::CounterNode*)1 |
| 711 : (blink::CounterNode*)0); | 711 : (blink::CounterNode*)0); |
| 712 } | 712 } |
| 713 fflush(stderr); | 713 fflush(stderr); |
| 714 } | 714 } |
| 715 | 715 |
| 716 #endif // NDEBUG | 716 #endif // NDEBUG |
| OLD | NEW |