Chromium Code Reviews| Index: Source/core/rendering/RenderListItem.cpp |
| diff --git a/Source/core/rendering/RenderListItem.cpp b/Source/core/rendering/RenderListItem.cpp |
| index 014cec2543015fe28950c21179c2986cfa8d5f36..0d81c20f004bc3d4be7f842cf656980397ed12f2 100644 |
| --- a/Source/core/rendering/RenderListItem.cpp |
| +++ b/Source/core/rendering/RenderListItem.cpp |
| @@ -26,6 +26,7 @@ |
| #include "core/HTMLNames.h" |
| #include "core/dom/NodeRenderingTraversal.h" |
| +#include "core/dom/MarkerPseudoElement.h" |
| #include "core/html/HTMLOListElement.h" |
| #include "core/rendering/RenderListMarker.h" |
| #include "core/rendering/RenderView.h" |
| @@ -57,14 +58,16 @@ void RenderListItem::styleDidChange(StyleDifference diff, const RenderStyle* old |
| { |
| RenderBlockFlow::styleDidChange(diff, oldStyle); |
| - if (style()->listStyleType() != NoneListStyle |
| - || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurred())) { |
| - if (!m_marker) |
| - m_marker = RenderListMarker::createAnonymous(this); |
| - m_marker->listItemStyleDidChange(); |
| - } else if (m_marker) { |
| - m_marker->destroy(); |
| - m_marker = nullptr; |
| + if (!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
|
Julien - ping for review
2014/12/05 19:44:04
We prefer early return.
dsinclair
2015/01/23 20:46:36
Done.
|
| + if (style()->listStyleType() != NoneListStyle |
| + || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurred())) { |
| + if (!m_marker) |
| + m_marker = RenderListMarker::createAnonymous(this); |
| + m_marker->listItemStyleDidChange(); |
| + } else if (m_marker) { |
| + m_marker->destroy(); |
| + m_marker = nullptr; |
| + } |
| } |
| } |
| @@ -74,6 +77,7 @@ void RenderListItem::willBeDestroyed() |
| m_marker->destroy(); |
| m_marker = nullptr; |
| } |
| + |
| RenderBlockFlow::willBeDestroyed(); |
| } |
| @@ -219,60 +223,27 @@ void RenderListItem::updateValueNow() const |
| bool RenderListItem::isEmpty() const |
| { |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) |
| + return isEmpty(); |
|
Julien - ping for review
2014/12/05 19:44:04
Really nice infinite loop?
dsinclair
2015/01/23 20:46:36
Done.
|
| return lastChild() == m_marker; |
| } |
| -static RenderObject* getParentOfFirstLineBox(RenderBlockFlow* curr, RenderObject* marker) |
| -{ |
| - RenderObject* firstChild = curr->firstChild(); |
| - if (!firstChild) |
| - return 0; |
| - |
| - bool inQuirksMode = curr->document().inQuirksMode(); |
| - for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) { |
| - if (currChild == marker) |
| - continue; |
| - |
| - if (currChild->isInline() && (!currChild->isRenderInline() || curr->generatesLineBoxesForInlineChild(currChild))) |
| - return curr; |
| - |
| - if (currChild->isFloating() || currChild->isOutOfFlowPositioned()) |
| - continue; |
| - |
| - if (!currChild->isRenderBlockFlow() || (currChild->isBox() && toRenderBox(currChild)->isWritingModeRoot())) |
| - break; |
| - |
| - if (curr->isListItem() && inQuirksMode && currChild->node() && |
| - (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*currChild->node()))) |
| - break; |
| - |
| - RenderObject* lineBox = getParentOfFirstLineBox(toRenderBlockFlow(currChild), marker); |
| - if (lineBox) |
| - return lineBox; |
| - } |
| - |
| - return 0; |
| -} |
| - |
| void RenderListItem::updateValue() |
| { |
| if (!m_hasExplicitValue) { |
| m_isValueUpToDate = false; |
| - if (m_marker) |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| + if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) |
| + element->renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); |
| + } else if (m_marker) { |
| m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); |
| + } |
| } |
| } |
| -static RenderObject* firstNonMarkerChild(RenderObject* parent) |
| -{ |
| - RenderObject* result = parent->slowFirstChild(); |
| - while (result && result->isListMarker()) |
| - result = result->nextSibling(); |
| - return result; |
| -} |
| - |
| void RenderListItem::updateMarkerLocationAndInvalidateWidth() |
| { |
| + ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()); |
| ASSERT(m_marker); |
| // FIXME: We should not modify the structure of the render tree |
| @@ -288,9 +259,11 @@ void RenderListItem::updateMarkerLocationAndInvalidateWidth() |
| bool RenderListItem::updateMarkerLocation() |
| { |
| + ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()); |
| ASSERT(m_marker); |
| + |
| RenderObject* markerParent = m_marker->parent(); |
| - RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); |
| + RenderObject* lineBoxParent = MarkerPseudoElement::getParentOfFirstLineBox(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 |
| @@ -303,7 +276,7 @@ bool RenderListItem::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() && !toRenderBlock(markerParent)->firstChild() && !toRenderBlock(markerParent)->continuation()) |
| @@ -318,7 +291,23 @@ void RenderListItem::layout() |
| { |
| ASSERT(needsLayout()); |
| - if (m_marker) { |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| + if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { |
| + ASSERT(element->renderer()->isListMarker()); |
| + RenderListMarker* marker = toRenderListMarker(element->renderer()); |
| + |
| + // 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. |
| + if (TextAutosizer* textAutosizer = document().textAutosizer()) |
| + textAutosizer->inflateListItem(this, marker); |
| + |
| + marker->updateMarginsAndContent(); |
| + if (marker->isInside()) |
| + containingBlock()->updateLogicalWidth(); |
| + } |
| + |
| + } 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. |
| @@ -334,23 +323,32 @@ void RenderListItem::layout() |
| void RenderListItem::addOverflowFromChildren() |
| { |
| RenderBlockFlow::addOverflowFromChildren(); |
| - positionListMarker(); |
| + |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| + MarkerPseudoElement* markerElement = toMarkerPseudoElement(toElement(node())->pseudoElement(MARKER)); |
| + if (markerElement && markerElement->renderer()) { |
| + ASSERT(markerElement->renderer()->isListMarker()); |
| + positionListMarker(toRenderListMarker(markerElement->renderer())); |
| + } |
| + } else { |
| + positionListMarker(m_marker); |
| + } |
| } |
| -void RenderListItem::positionListMarker() |
| +void RenderListItem::positionListMarker(RenderListMarker* marker) |
| { |
| - if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_marker->inlineBoxWrapper()) { |
| - LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); |
| + if (marker && marker->parent()->isBox() && !marker->isInside() && marker->inlineBoxWrapper()) { |
| + LayoutUnit markerOldLogicalLeft = marker->logicalLeft(); |
| LayoutUnit blockOffset = 0; |
| LayoutUnit lineOffset = 0; |
| - for (RenderBox* o = m_marker->parentBox(); o != this; o = o->parentBox()) { |
| + for (RenderBox* 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(); |
| @@ -359,9 +357,9 @@ void RenderListItem::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) { |
| @@ -382,18 +380,18 @@ void RenderListItem::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; |
| } |
| @@ -405,10 +403,10 @@ void RenderListItem::positionListMarker() |
| } |
| if (adjustOverflow) { |
| - LayoutRect markerRect(markerLogicalLeft + lineOffset, blockOffset, m_marker->width(), m_marker->height()); |
| + LayoutRect markerRect(markerLogicalLeft + lineOffset, blockOffset, marker->width(), marker->height()); |
| if (!style()->isHorizontalWritingMode()) |
| markerRect = markerRect.transposedRect(); |
| - RenderBox* o = m_marker; |
| + RenderBox* o = marker; |
| bool propagateVisualOverflow = true; |
| bool propagateLayoutOverflow = true; |
| do { |
| @@ -441,15 +439,28 @@ void RenderListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO |
| const String& RenderListItem::markerText() const |
| { |
| - if (m_marker) |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| + if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { |
| + if (element->renderer()) { |
| + ASSERT(element->renderer()->isListMarker()); |
| + return toRenderListMarker(element->renderer())->text(); |
| + } |
| + } |
| + } else if (m_marker) { |
| return m_marker->text(); |
| + } |
| return nullAtom.string(); |
| } |
| void RenderListItem::explicitValueChanged() |
| { |
| - if (m_marker) |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| + if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) |
| + element->renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); |
| + } else if (m_marker) { |
| m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); |
| + } |
| + |
| Node* listNode = enclosingList(this); |
| for (RenderListItem* item = this; item; item = nextListItem(listNode, item)) |
| item->updateValue(); |
| @@ -481,8 +492,15 @@ void RenderListItem::clearExplicitValue() |
| void RenderListItem::setNotInList(bool notInList) |
| { |
| m_notInList = notInList; |
| - if (m_marker) |
| + if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| + if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { |
| + ASSERT(element->renderer()); |
| + ASSERT(element->renderer()->isListMarker()); |
| + toRenderListMarker(element->renderer())->updateMarginsAndContent(); |
| + } |
| + } else if (m_marker) { |
| updateMarkerLocation(); |
| + } |
| } |
| static RenderListItem* previousOrNextItem(bool isListReversed, Node* list, RenderListItem* item) |