Chromium Code Reviews| Index: Source/core/dom/MarkerPseudoElement.cpp |
| diff --git a/Source/core/dom/MarkerPseudoElement.cpp b/Source/core/dom/MarkerPseudoElement.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e5130e20da279cb896fc9a9a34f1ce6dbff8fd19 |
| --- /dev/null |
| +++ b/Source/core/dom/MarkerPseudoElement.cpp |
| @@ -0,0 +1,149 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "config.h" |
| +#include "core/dom/MarkerPseudoElement.h" |
| + |
| +#include "core/layout/LayoutBlockFlow.h" |
| +#include "core/layout/LayoutListItem.h" |
| +#include "core/layout/LayoutListMarker.h" |
| + |
| +namespace blink { |
| + |
| +MarkerPseudoElement::MarkerPseudoElement(Element* parent) |
| + : PseudoElement(parent, MARKER) |
| +{ |
| +} |
| + |
| +MarkerPseudoElement::~MarkerPseudoElement() |
| +{ |
| +} |
| + |
| +LayoutObject* MarkerPseudoElement::parentOfFirstLineBox(LayoutBlockFlow* curr, const LayoutObject* marker) |
| +{ |
| + LayoutObject* firstChild = curr->firstChild(); |
| + if (!firstChild) |
| + return nullptr; |
| + |
| + 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; |
| + |
| + if (LayoutObject* lineBox = parentOfFirstLineBox(toLayoutBlockFlow(currChild), marker)) |
| + return lineBox; |
| + } |
| + |
| + return nullptr; |
| +} |
| + |
| +PassRefPtr<ComputedStyle> MarkerPseudoElement::customStyleForLayoutObject() |
| +{ |
| + if (!layoutObject()) |
|
esprehn
2015/04/22 07:45:45
This isn't right, you should never look at the lay
dsinclair
2015/04/22 20:00:38
Removed customStyleForLayoutObjects and did calls
|
| + return nullptr; |
| + |
| + LayoutObject* parent = layoutObject()->parent(); |
|
esprehn
2015/04/22 07:45:45
You need to call LayoutTreeBuilderTraversal::paren
dsinclair
2015/04/22 20:00:38
Removed.
|
| + if (!parent) |
| + return nullptr; |
| + |
| + return styleForListMarkerLayoutObject(*parent, layoutObject()->style()); |
| +} |
| + |
| +PassRefPtr<ComputedStyle> MarkerPseudoElement::styleForListMarkerLayoutObject(LayoutObject& parent, const ComputedStyle* style) |
|
esprehn
2015/04/22 07:45:45
styleForListMarker(...) no need for LayoutObject i
dsinclair
2015/04/22 20:00:38
Done.
|
| +{ |
| + RefPtr<ComputedStyle> newStyle = ComputedStyle::create(); |
| + |
| + // The marker always inherits from the list item, regardless of where it might end |
| + // up (e.g., in some deeply nested line box). See CSS3 spec. |
| + newStyle->inheritFrom(*parent.style()); |
| + if (style) { |
| + // Reuse the current margins. Otherwise resetting the margins to initial values |
| + // would trigger unnecessary layout. |
| + newStyle->setMarginStart(style->marginStart()); |
| + newStyle->setMarginEnd(style->marginRight()); |
|
esprehn
2015/04/22 07:45:45
This code should just be inlined in the above meth
dsinclair
2015/04/22 20:00:38
It can be in the future when we remove the old cod
|
| + } |
| + return newStyle; |
| +} |
| + |
| +LayoutObject* MarkerPseudoElement::firstNonMarkerChild(LayoutObject* parent) |
| +{ |
| + LayoutObject* result = parent->slowFirstChild(); |
| + while (result && result->isListMarker()) |
| + result = result->nextSibling(); |
| + return result; |
| +} |
| + |
| +LayoutObject* MarkerPseudoElement::createLayoutObject(const ComputedStyle& style) |
| +{ |
| + ASSERT(parentElement()->layoutObject()); |
| + LayoutListMarker* marker = new LayoutListMarker(this, toLayoutListItem(parentElement()->layoutObject())); |
| + marker->setStyle(ComputedStyle::clone(style)); |
|
esprehn
2015/04/22 07:45:45
Don't clone the style, you never need to do that i
dsinclair
2015/04/22 20:00:38
Done.
|
| + return marker; |
| +} |
| + |
| +void MarkerPseudoElement::attachListMarkerLayoutObject() |
| +{ |
| + LayoutListItem* parentLayoutObject = toLayoutListItem(parentElement()->layoutObject()); |
| + ASSERT(parentLayoutObject); |
| + ASSERT(layoutObject()); |
| + |
| + LayoutListMarker* marker = toLayoutListMarker(layoutObject()); |
| + LayoutObject* markerParent = marker->parent(); |
| + |
| + LayoutObject* insertionLayoutObject = MarkerPseudoElement::parentOfFirstLineBox(parentLayoutObject, marker); |
| + |
| + // We didn't find any line boxes so make the insertion point the LI layoutObject. |
| + if (!insertionLayoutObject) |
| + insertionLayoutObject = parentLayoutObject; |
| + ASSERT(insertionLayoutObject); |
| + |
| + // Check if we're already inserted into the right parent as the first child. |
| + if (markerParent && marker == markerParent->slowFirstChild() |
| + && (markerParent == insertionLayoutObject || markerParent == insertionLayoutObject->slowFirstChild())) |
| + return; |
| + |
| + marker->remove(); |
| + insertionLayoutObject->addChild(marker, MarkerPseudoElement::firstNonMarkerChild(insertionLayoutObject)); |
| + marker->updateMarginsAndContent(); |
|
esprehn
2015/04/22 07:45:45
Layout calls this for isImage(), make it call it e
dsinclair
2015/04/22 20:00:38
That will mean we'll do it on every layout, where
|
| + |
| + // If markerParent is an anonymous block with no children, destroy it. |
| + if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(markerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation()) |
| + markerParent->destroy(); |
| + |
| + if (marker->isInside()) |
| + parentLayoutObject->containingBlock()->updateLogicalWidth(); |
|
esprehn
2015/04/22 07:45:45
You can't update logical widths inside style recal
dsinclair
2015/04/22 20:00:38
Done.
|
| +} |
| + |
| +void MarkerPseudoElement::attach(const AttachContext& context) |
| +{ |
| + PseudoElement::attach(context); |
| + ASSERT(layoutObject()); |
| + |
| + LayoutListMarker* marker = toLayoutListMarker(layoutObject()); |
| + |
| + RefPtr<ComputedStyle> newStyle = MarkerPseudoElement::styleForListMarkerLayoutObject(*(marker->mutableListItem()), marker->style()); |
| + marker->setStyle(newStyle.release()); |
|
esprehn
2015/04/22 07:45:45
::attach went through the customStyleForLayoutObje
dsinclair
2015/04/22 20:00:38
Style is set here only now.
|
| + |
| + attachListMarkerLayoutObject(); |
| +} |
| + |
| +void MarkerPseudoElement::didRecalcStyle(StyleRecalcChange) |
| +{ |
| + attachListMarkerLayoutObject(); |
| +} |
| + |
| +} // namespace blink |