| Index: third_party/WebKit/Source/core/layout/LayoutCounter.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/LayoutCounter.cpp b/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
|
| index 14a2c72c93c37bddc8ff09c57047d028387e4308..542a70ff669aaf7f9d21a57097770e60df841719 100644
|
| --- a/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
|
| @@ -43,7 +43,7 @@ using namespace HTMLNames;
|
| typedef HashMap<AtomicString, RefPtr<CounterNode>> CounterMap;
|
| typedef HashMap<const LayoutObject*, OwnPtr<CounterMap>> CounterMaps;
|
|
|
| -static CounterNode* makeCounterNode(LayoutObject&, const AtomicString& identifier, bool alwaysCreateCounter);
|
| +static CounterNode* makeCounterNodeIfNeeded(LayoutObject&, const AtomicString& identifier, bool alwaysCreateCounter);
|
|
|
| // See class definition as to why we have this map.
|
| static CounterMaps& counterMaps()
|
| @@ -52,21 +52,43 @@ static CounterMaps& counterMaps()
|
| return staticCounterMaps;
|
| }
|
|
|
| +Element* ancestorStyleContainmentObject(const Element& element)
|
| +{
|
| + for (Element* ancestor = FlatTreeTraversal::parentElement(element); ancestor; ancestor = FlatTreeTraversal::parentElement(*ancestor)) {
|
| + if (ancestor->layoutObject() && ancestor->layoutObject()->style()->containsStyle())
|
| + return ancestor;
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| // This function processes the layoutObject tree in the order of the DOM tree
|
| -// including pseudo elements as defined in CSS 2.1.
|
| -static LayoutObject* previousInPreOrder(const LayoutObject& object)
|
| +// including pseudo elements as defined in CSS 2.1. This method will always return
|
| +// either a previous object within the same contain: style scope or nullptr.
|
| +static LayoutObject* previousInPreOrderRespectingContainment(const LayoutObject& object)
|
| {
|
| Element* self = toElement(object.node());
|
| ASSERT(self);
|
| Element* previous = ElementTraversal::previousIncludingPseudo(*self);
|
| - while (previous && !previous->layoutObject())
|
| - previous = ElementTraversal::previousIncludingPseudo(*previous);
|
| - return previous ? previous->layoutObject() : 0;
|
| + Element* styleContainAncestor = ancestorStyleContainmentObject(*self);
|
| +
|
| + while (1) {
|
| + while (previous && !previous->layoutObject())
|
| + previous = ElementTraversal::previousIncludingPseudo(*previous);
|
| + if (!previous)
|
| + return nullptr;
|
| + Element* previousStyleContainAncestor = ancestorStyleContainmentObject(*previous);
|
| + if (previousStyleContainAncestor == styleContainAncestor)
|
| + return previous->layoutObject();
|
| + if (!previousStyleContainAncestor)
|
| + return nullptr;
|
| + previous = previousStyleContainAncestor;
|
| + }
|
| }
|
|
|
| // This function processes the layoutObject tree in the order of the DOM tree
|
| -// including pseudo elements as defined in CSS 2.1.
|
| -static LayoutObject* previousSiblingOrParent(const LayoutObject& object)
|
| +// including pseudo elements as defined in CSS 2.1. This method avoids crossing
|
| +// contain: style boundaries.
|
| +static LayoutObject* previousSiblingOrParentRespectingContainment(const LayoutObject& object)
|
| {
|
| Element* self = toElement(object.node());
|
| ASSERT(self);
|
| @@ -76,7 +98,7 @@ static LayoutObject* previousSiblingOrParent(const LayoutObject& object)
|
| if (previous)
|
| return previous->layoutObject();
|
| previous = self->parentElement();
|
| - return previous ? previous->layoutObject() : 0;
|
| + return previous && previous->layoutObject() && !(previous->layoutObject()->style()->contain() & ContainsStyle) ? previous->layoutObject() : nullptr;
|
| }
|
|
|
| static inline Element* parentElement(LayoutObject& object)
|
| @@ -98,7 +120,7 @@ static LayoutObject* nextInPreOrder(const LayoutObject& object, const Element* s
|
| Element* next = skipDescendants ? ElementTraversal::nextIncludingPseudoSkippingChildren(*self, stayWithin) : ElementTraversal::nextIncludingPseudo(*self, stayWithin);
|
| while (next && !next->layoutObject())
|
| next = skipDescendants ? ElementTraversal::nextIncludingPseudoSkippingChildren(*next, stayWithin) : ElementTraversal::nextIncludingPseudo(*next, stayWithin);
|
| - return next ? next->layoutObject() : 0;
|
| + return next ? next->layoutObject() : nullptr;
|
| }
|
|
|
| static bool planCounter(LayoutObject& object, const AtomicString& identifier, bool& isReset, int& value)
|
| @@ -182,16 +204,16 @@ static bool findPlaceForCounter(LayoutObject& counterOwner, const AtomicString&
|
| {
|
| // We cannot stop searching for counters with the same identifier before we also
|
| // check this layoutObject, because it may affect the positioning in the tree of our counter.
|
| - LayoutObject* searchEndLayoutObject = previousSiblingOrParent(counterOwner);
|
| + LayoutObject* searchEndLayoutObject = previousSiblingOrParentRespectingContainment(counterOwner);
|
| // We check layoutObjects in preOrder from the layoutObject that our counter is attached to
|
| // towards the beginning of the document for counters with the same identifier as the one
|
| // we are trying to find a place for. This is the next layoutObject to be checked.
|
| - LayoutObject* currentLayoutObject = previousInPreOrder(counterOwner);
|
| + LayoutObject* currentLayoutObject = previousInPreOrderRespectingContainment(counterOwner);
|
| previousSibling = nullptr;
|
| RefPtr<CounterNode> previousSiblingProtector = nullptr;
|
|
|
| while (currentLayoutObject) {
|
| - CounterNode* currentCounter = makeCounterNode(*currentLayoutObject, identifier, false);
|
| + CounterNode* currentCounter = makeCounterNodeIfNeeded(*currentLayoutObject, identifier, false);
|
| if (searchEndLayoutObject == currentLayoutObject) {
|
| // We may be at the end of our search.
|
| if (currentCounter) {
|
| @@ -204,7 +226,7 @@ static bool findPlaceForCounter(LayoutObject& counterOwner, const AtomicString&
|
| // hence we are the next sibling of that counter if that reset is not a root or
|
| // we are a root node if that reset is a root.
|
| parent = currentCounter->parent();
|
| - previousSibling = parent ? currentCounter : 0;
|
| + previousSibling = parent ? currentCounter : nullptr;
|
| return parent;
|
| }
|
| // We are not a reset node or the previous reset must be on an ancestor of our owner layoutObject
|
| @@ -257,7 +279,7 @@ static bool findPlaceForCounter(LayoutObject& counterOwner, const AtomicString&
|
| // good counter, or we are a reset node and the counter on the previous sibling
|
| // of our owner layoutObject was not a reset counter.
|
| // Set a new goal for the end of the search.
|
| - searchEndLayoutObject = previousSiblingOrParent(*currentLayoutObject);
|
| + searchEndLayoutObject = previousSiblingOrParentRespectingContainment(*currentLayoutObject);
|
| } else {
|
| // We are searching descendants of a previous sibling of the layoutObject that the
|
| // counter being placed is attached to.
|
| @@ -277,7 +299,7 @@ static bool findPlaceForCounter(LayoutObject& counterOwner, const AtomicString&
|
| } else {
|
| previousSiblingProtector = currentCounter;
|
| }
|
| - currentLayoutObject = previousSiblingOrParent(*currentLayoutObject);
|
| + currentLayoutObject = previousSiblingOrParentRespectingContainment(*currentLayoutObject);
|
| continue;
|
| }
|
| }
|
| @@ -286,14 +308,14 @@ static bool findPlaceForCounter(LayoutObject& counterOwner, const AtomicString&
|
| // performance improvement would create more code duplication than is worthwhile in my opinion and may further
|
| // impede the readability of this already complex algorithm.
|
| if (previousSiblingProtector)
|
| - currentLayoutObject = previousSiblingOrParent(*currentLayoutObject);
|
| + currentLayoutObject = previousSiblingOrParentRespectingContainment(*currentLayoutObject);
|
| else
|
| - currentLayoutObject = previousInPreOrder(*currentLayoutObject);
|
| + currentLayoutObject = previousInPreOrderRespectingContainment(*currentLayoutObject);
|
| }
|
| return false;
|
| }
|
|
|
| -static CounterNode* makeCounterNode(LayoutObject& object, const AtomicString& identifier, bool alwaysCreateCounter)
|
| +static CounterNode* makeCounterNodeIfNeeded(LayoutObject& object, const AtomicString& identifier, bool alwaysCreateCounter)
|
| {
|
| if (object.hasCounterNodeMap()) {
|
| if (CounterMap* nodeMap = counterMaps().get(&object)) {
|
| @@ -383,7 +405,7 @@ PassRefPtr<StringImpl> LayoutCounter::originalText() const
|
| break;
|
| beforeAfterContainer = beforeAfterContainer->parent();
|
| }
|
| - makeCounterNode(*beforeAfterContainer, m_counter.identifier(), true)->addLayoutObject(const_cast<LayoutCounter*>(this));
|
| + makeCounterNodeIfNeeded(*beforeAfterContainer, m_counter.identifier(), true)->addLayoutObject(const_cast<LayoutCounter*>(this));
|
| ASSERT(m_counterNode);
|
| }
|
| CounterNode* child = m_counterNode;
|
| @@ -496,7 +518,7 @@ static void updateCounters(LayoutObject& layoutObject)
|
| CounterDirectiveMap::const_iterator end = directiveMap->end();
|
| if (!layoutObject.hasCounterNodeMap()) {
|
| for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it)
|
| - makeCounterNode(layoutObject, it->key, false);
|
| + makeCounterNodeIfNeeded(layoutObject, it->key, false);
|
| return;
|
| }
|
| CounterMap* counterMap = counterMaps().get(&layoutObject);
|
| @@ -504,7 +526,7 @@ static void updateCounters(LayoutObject& layoutObject)
|
| for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) {
|
| RefPtr<CounterNode> node = counterMap->get(it->key);
|
| if (!node) {
|
| - makeCounterNode(layoutObject, it->key, false);
|
| + makeCounterNodeIfNeeded(layoutObject, it->key, false);
|
| continue;
|
| }
|
| RefPtr<CounterNode> newParent = nullptr;
|
| @@ -560,7 +582,7 @@ void LayoutCounter::layoutObjectStyleChanged(LayoutObject& layoutObject, const C
|
| // We must create this node here, because the changed node may be a node with no display such as
|
| // as those created by the increment or reset directives and the re-layout that will happen will
|
| // not catch the change if the node had no children.
|
| - makeCounterNode(layoutObject, it->key, false);
|
| + makeCounterNodeIfNeeded(layoutObject, it->key, false);
|
| }
|
| // Destroying old counters that do not exist in the new counterDirective map.
|
| for (CounterDirectiveMap::const_iterator it = oldCounterDirectives->begin(); it !=oldMapEnd; ++it) {
|
| @@ -579,7 +601,7 @@ void LayoutCounter::layoutObjectStyleChanged(LayoutObject& layoutObject, const C
|
| // We must create this node here, because the added node may be a node with no display such as
|
| // as those created by the increment or reset directives and the re-layout that will happen will
|
| // not catch the change if the node had no children.
|
| - makeCounterNode(layoutObject, it->key, false);
|
| + makeCounterNodeIfNeeded(layoutObject, it->key, false);
|
| }
|
| }
|
| }
|
|
|