| Index: Source/core/layout/LayoutListItem.cpp
|
| diff --git a/Source/core/layout/LayoutListItem.cpp b/Source/core/layout/LayoutListItem.cpp
|
| index 96fddad21f98b5e09296f7d48fb5d85253be63e7..8620da8d3560bb49a8960fcf989bb5abdf2d4e73 100644
|
| --- a/Source/core/layout/LayoutListItem.cpp
|
| +++ b/Source/core/layout/LayoutListItem.cpp
|
| @@ -25,12 +25,14 @@
|
| #include "core/layout/LayoutListItem.h"
|
|
|
| #include "core/HTMLNames.h"
|
| +#include "core/dom/MarkerPseudoElement.h"
|
| #include "core/dom/shadow/ComposedTreeTraversal.h"
|
| #include "core/html/HTMLOListElement.h"
|
| #include "core/layout/LayoutListMarker.h"
|
| #include "core/layout/LayoutView.h"
|
| #include "core/layout/TextAutosizer.h"
|
| #include "wtf/StdLibExtras.h"
|
| +#include "wtf/TemporaryChange.h"
|
| #include "wtf/text/StringBuilder.h"
|
|
|
| namespace blink {
|
| @@ -45,12 +47,16 @@ LayoutListItem::LayoutListItem(Element* element)
|
| , m_notInList(false)
|
| {
|
| setInline(false);
|
| + setConsumesSubtreeChangeNotification();
|
| }
|
|
|
| void LayoutListItem::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
|
| {
|
| LayoutBlockFlow::styleDidChange(diff, oldStyle);
|
|
|
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled())
|
| + return;
|
| +
|
| if (style()->listStyleType() != NoneListStyle
|
| || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurred())) {
|
| if (!m_marker)
|
| @@ -65,7 +71,8 @@ void LayoutListItem::styleDidChange(StyleDifference diff, const ComputedStyle* o
|
| void LayoutListItem::willBeDestroyed()
|
| {
|
| if (m_marker) {
|
| - m_marker->destroy();
|
| + if (!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled())
|
| + m_marker->destroy();
|
| m_marker = nullptr;
|
| }
|
| LayoutBlockFlow::willBeDestroyed();
|
| @@ -74,17 +81,26 @@ void LayoutListItem::willBeDestroyed()
|
| void LayoutListItem::insertedIntoTree()
|
| {
|
| LayoutBlockFlow::insertedIntoTree();
|
| -
|
| updateListMarkerNumbers();
|
| }
|
|
|
| void LayoutListItem::willBeRemovedFromTree()
|
| {
|
| LayoutBlockFlow::willBeRemovedFromTree();
|
| -
|
| updateListMarkerNumbers();
|
| }
|
|
|
| +// FIXME: This causes subtree modifications, which will set the flags and we'll
|
| +// end up doing the check a second time next frame ....
|
| +void LayoutListItem::subtreeDidChange()
|
| +{
|
| + if (documentBeingDestroyed())
|
| + return;
|
| +
|
| + if (PseudoElement* element = toElement(node())->pseudoElement(MARKER))
|
| + toMarkerPseudoElement(element)->attachListMarker();
|
| +}
|
| +
|
| static bool isList(const Node& node)
|
| {
|
| return isHTMLUListElement(node) || isHTMLOListElement(node);
|
| @@ -129,11 +145,11 @@ static LayoutListItem* nextListItem(const Node* listNode, const LayoutListItem*
|
| continue;
|
| }
|
|
|
| - LayoutObject* renderer = current->layoutObject();
|
| - if (renderer && renderer->isListItem())
|
| - return toLayoutListItem(renderer);
|
| + LayoutObject* layoutObject = current->layoutObject();
|
| + if (layoutObject && layoutObject->isListItem())
|
| + return toLayoutListItem(layoutObject);
|
|
|
| - // FIXME: Can this be optimized to skip the children of the elements without a renderer?
|
| + // FIXME: Can this be optimized to skip the children of the elements without a layoutObject?
|
| current = LayoutTreeBuilderTraversal::next(*current, listNode);
|
| }
|
|
|
| @@ -146,14 +162,17 @@ static LayoutListItem* previousListItem(const Node* listNode, const LayoutListIt
|
| Node* current = item->node();
|
| ASSERT(current);
|
| ASSERT(!current->document().childNeedsDistributionRecalc());
|
| - for (current = LayoutTreeBuilderTraversal::previous(*current, listNode); current && current != listNode; current = LayoutTreeBuilderTraversal::previous(*current, listNode)) {
|
| - LayoutObject* renderer = current->layoutObject();
|
| - if (!renderer || (renderer && !renderer->isListItem()))
|
| + for (current = LayoutTreeBuilderTraversal::previous(*current, listNode);
|
| + current && current != listNode;
|
| + current = LayoutTreeBuilderTraversal::previous(*current, listNode)) {
|
| +
|
| + LayoutObject* layoutObject = current->layoutObject();
|
| + if (!layoutObject || (layoutObject && !layoutObject->isListItem()))
|
| continue;
|
| - Node* otherList = enclosingList(toLayoutListItem(renderer));
|
| + Node* otherList = enclosingList(toLayoutListItem(layoutObject));
|
| // This item is part of our current list, so it's what we're looking for.
|
| if (listNode == otherList)
|
| - return toLayoutListItem(renderer);
|
| + return toLayoutListItem(layoutObject);
|
| // We found ourself inside another list; lets skip the rest of it.
|
| // Use nextIncludingPseudo() here because the other list itself may actually
|
| // be a list item itself. We need to examine it, so we do this to counteract
|
| @@ -216,57 +235,20 @@ bool LayoutListItem::isEmpty() const
|
| return lastChild() == m_marker;
|
| }
|
|
|
| -static LayoutObject* getParentOfFirstLineBox(LayoutBlockFlow* curr, LayoutObject* marker)
|
| -{
|
| - LayoutObject* firstChild = curr->firstChild();
|
| - if (!firstChild)
|
| - return 0;
|
| -
|
| - bool inQuirksMode = curr->document().inQuirksMode();
|
| - for (LayoutObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) {
|
| - if (currChild == marker)
|
| - continue;
|
| -
|
| - if (currChild->isInline() && (!currChild->isLayoutInline() || curr->generatesLineBoxesForInlineChild(currChild)))
|
| - return curr;
|
| -
|
| - if (currChild->isFloating() || currChild->isOutOfFlowPositioned())
|
| - continue;
|
| -
|
| - if (!currChild->isLayoutBlockFlow() || (currChild->isBox() && toLayoutBox(currChild)->isWritingModeRoot()))
|
| - break;
|
| -
|
| - if (curr->isListItem() && inQuirksMode && currChild->node()
|
| - && (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*currChild->node())))
|
| - break;
|
| -
|
| - LayoutObject* lineBox = getParentOfFirstLineBox(toLayoutBlockFlow(currChild), marker);
|
| - if (lineBox)
|
| - return lineBox;
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| void LayoutListItem::updateValue()
|
| {
|
| - if (!m_hasExplicitValue) {
|
| - m_isValueUpToDate = false;
|
| - if (m_marker)
|
| - m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::ListValueChange);
|
| - }
|
| -}
|
| + if (m_hasExplicitValue)
|
| + return;
|
|
|
| -static LayoutObject* firstNonMarkerChild(LayoutObject* parent)
|
| -{
|
| - LayoutObject* result = parent->slowFirstChild();
|
| - while (result && result->isListMarker())
|
| - result = result->nextSibling();
|
| - return result;
|
| + m_isValueUpToDate = false;
|
| +
|
| + if (m_marker)
|
| + m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::ListValueChange);
|
| }
|
|
|
| void LayoutListItem::updateMarkerLocationAndInvalidateWidth()
|
| {
|
| + ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled());
|
| ASSERT(m_marker);
|
|
|
| // FIXME: We should not modify the structure of the render tree
|
| @@ -296,9 +278,11 @@ void LayoutListItem::updateMarkerLocationAndInvalidateWidth()
|
|
|
| bool LayoutListItem::updateMarkerLocation()
|
| {
|
| + ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled());
|
| ASSERT(m_marker);
|
| +
|
| LayoutObject* markerParent = m_marker->parent();
|
| - LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
|
| + LayoutObject* lineBoxParent = MarkerPseudoElement::parentOfFirstLineBox(this, m_marker);
|
| if (!lineBoxParent) {
|
| // If the marker is currently contained inside an anonymous box, then we
|
| // are the only item in that anonymous box (since no line box parent was
|
| @@ -311,10 +295,11 @@ bool LayoutListItem::updateMarkerLocation()
|
|
|
| if (markerParent != lineBoxParent) {
|
| m_marker->remove();
|
| - lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
|
| + lineBoxParent->addChild(m_marker, MarkerPseudoElement::firstNonMarkerChild(lineBoxParent));
|
| m_marker->updateMarginsAndContent();
|
| // If markerParent is an anonymous block with no children, destroy it.
|
| - if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(markerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation())
|
| + if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(markerParent)->firstChild()
|
| + && !toLayoutBlock(markerParent)->continuation())
|
| markerParent->destroy();
|
| return true;
|
| }
|
| @@ -326,7 +311,11 @@ void LayoutListItem::layout()
|
| {
|
| ASSERT(needsLayout());
|
|
|
| - if (m_marker) {
|
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) {
|
| + if (m_marker)
|
| + m_marker->updateMarginsAndContent();
|
| +
|
| + } else if (m_marker) {
|
| // The marker must be autosized before calling
|
| // updateMarkerLocationAndInvalidateWidth. It cannot be done in the
|
| // parent's beginLayout because it is not yet in the render tree.
|
| @@ -342,23 +331,27 @@ void LayoutListItem::layout()
|
| void LayoutListItem::addOverflowFromChildren()
|
| {
|
| LayoutBlockFlow::addOverflowFromChildren();
|
| - positionListMarker();
|
| + positionListMarker(m_marker);
|
| }
|
|
|
| -void LayoutListItem::positionListMarker()
|
| +void LayoutListItem::positionListMarker(LayoutListMarker* marker)
|
| {
|
| - if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_marker->inlineBoxWrapper()) {
|
| - LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft();
|
| + if (!marker)
|
| + return;
|
| +
|
| + ASSERT(marker->parent());
|
| + if (marker->parent()->isBox() && !marker->isInside() && marker->inlineBoxWrapper()) {
|
| + LayoutUnit markerOldLogicalLeft = marker->logicalLeft();
|
| LayoutUnit blockOffset = 0;
|
| LayoutUnit lineOffset = 0;
|
| - for (LayoutBox* o = m_marker->parentBox(); o != this; o = o->parentBox()) {
|
| + for (LayoutBox* o = marker->parentBox(); o != this; o = o->parentBox()) {
|
| blockOffset += o->logicalTop();
|
| lineOffset += o->logicalLeft();
|
| }
|
|
|
| bool adjustOverflow = false;
|
| LayoutUnit markerLogicalLeft;
|
| - RootInlineBox& root = m_marker->inlineBoxWrapper()->root();
|
| + RootInlineBox& root = marker->inlineBoxWrapper()->root();
|
| bool hitSelfPaintingLayer = false;
|
|
|
| LayoutUnit lineTop = root.lineTop();
|
| @@ -367,9 +360,9 @@ void LayoutListItem::positionListMarker()
|
| // FIXME: Need to account for relative positioning in the layout overflow.
|
| if (style()->isLeftToRightDirection()) {
|
| LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, logicalLeftOffsetForLine(blockOffset, false), false);
|
| - markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - borderStart() + m_marker->marginStart();
|
| - m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogicalLeft - markerOldLogicalLeft).toFloat());
|
| - for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
|
| + markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - borderStart() + marker->marginStart();
|
| + marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogicalLeft - markerOldLogicalLeft).toFloat());
|
| + for (InlineFlowBox* box = marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
|
| LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
|
| LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
|
| if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hitSelfPaintingLayer) {
|
| @@ -390,18 +383,18 @@ void LayoutListItem::positionListMarker()
|
| }
|
| } else {
|
| LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false);
|
| - markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd();
|
| - m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogicalLeft - markerOldLogicalLeft).toFloat());
|
| - for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
|
| + markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + marker->marginEnd();
|
| + marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogicalLeft - markerOldLogicalLeft).toFloat());
|
| + for (InlineFlowBox* box = marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
|
| LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
|
| LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
|
| - if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalVisualOverflowRect.maxX() && !hitSelfPaintingLayer) {
|
| - newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - newLogicalVisualOverflowRect.x());
|
| + if (markerLogicalLeft + marker->logicalWidth() > newLogicalVisualOverflowRect.maxX() && !hitSelfPaintingLayer) {
|
| + newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + marker->logicalWidth() - newLogicalVisualOverflowRect.x());
|
| if (box == root)
|
| adjustOverflow = true;
|
| }
|
| - if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalLayoutOverflowRect.maxX()) {
|
| - newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - newLogicalLayoutOverflowRect.x());
|
| + if (markerLogicalLeft + marker->logicalWidth() > newLogicalLayoutOverflowRect.maxX()) {
|
| + newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + marker->logicalWidth() - newLogicalLayoutOverflowRect.x());
|
| if (box == root)
|
| adjustOverflow = true;
|
| }
|
| @@ -413,10 +406,10 @@ void LayoutListItem::positionListMarker()
|
| }
|
|
|
| if (adjustOverflow) {
|
| - LayoutRect markerRect(LayoutPoint(markerLogicalLeft + lineOffset, blockOffset), m_marker->size());
|
| + LayoutRect markerRect(LayoutPoint(markerLogicalLeft + lineOffset, blockOffset), marker->size());
|
| if (!style()->isHorizontalWritingMode())
|
| markerRect = markerRect.transposedRect();
|
| - LayoutBox* o = m_marker;
|
| + LayoutBox* o = marker;
|
| bool propagateVisualOverflow = true;
|
| bool propagateLayoutOverflow = true;
|
| do {
|
| @@ -458,6 +451,7 @@ void LayoutListItem::explicitValueChanged()
|
| {
|
| if (m_marker)
|
| m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::ListValueChange);
|
| +
|
| Node* listNode = enclosingList(this);
|
| for (LayoutListItem* item = this; item; item = nextListItem(listNode, item))
|
| item->updateValue();
|
| @@ -489,7 +483,9 @@ void LayoutListItem::clearExplicitValue()
|
| void LayoutListItem::setNotInList(bool notInList)
|
| {
|
| m_notInList = notInList;
|
| - if (m_marker)
|
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled() && m_marker)
|
| + m_marker->updateMarginsAndContent();
|
| + else if (m_marker)
|
| updateMarkerLocation();
|
| }
|
|
|
|
|