OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/dom/MarkerPseudoElement.h" |
| 7 |
| 8 #include "core/layout/LayoutBlockFlow.h" |
| 9 #include "core/layout/LayoutListItem.h" |
| 10 #include "core/layout/LayoutListMarker.h" |
| 11 |
| 12 namespace blink { |
| 13 |
| 14 MarkerPseudoElement::MarkerPseudoElement(Element* parent) |
| 15 : PseudoElement(parent, MARKER) |
| 16 { |
| 17 } |
| 18 |
| 19 MarkerPseudoElement::~MarkerPseudoElement() |
| 20 { |
| 21 } |
| 22 |
| 23 LayoutObject* MarkerPseudoElement::parentOfFirstLineBox(LayoutObject* curr, cons
t LayoutObject* marker) |
| 24 { |
| 25 ASSERT(curr->isLayoutBlockFlow()); |
| 26 |
| 27 LayoutObject* firstChild = toLayoutBlockFlow(curr)->firstChild(); |
| 28 if (!firstChild) |
| 29 return nullptr; |
| 30 |
| 31 bool inQuirksMode = curr->document().inQuirksMode(); |
| 32 for (LayoutObject* currChild = firstChild; currChild; currChild = currChild-
>nextSibling()) { |
| 33 if (currChild == marker) |
| 34 continue; |
| 35 |
| 36 if (currChild->isInline() && (!currChild->isLayoutInline() || toLayoutBl
ockFlow(curr)->generatesLineBoxesForInlineChild(currChild))) |
| 37 return curr; |
| 38 |
| 39 if (currChild->isFloating() || currChild->isOutOfFlowPositioned()) |
| 40 continue; |
| 41 |
| 42 if (!currChild->isLayoutBlockFlow() || (currChild->isBox() && toLayoutBo
x(currChild)->isWritingModeRoot())) |
| 43 break; |
| 44 |
| 45 if (curr->isListItem() && inQuirksMode && currChild->node() |
| 46 && (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*cu
rrChild->node()))) |
| 47 break; |
| 48 |
| 49 if (LayoutObject* lineBox = parentOfFirstLineBox(toLayoutBlockFlow(currC
hild), marker)) |
| 50 return lineBox; |
| 51 } |
| 52 |
| 53 return nullptr; |
| 54 } |
| 55 |
| 56 PassRefPtr<ComputedStyle> MarkerPseudoElement::styleForListMarker(LayoutObject&
parent, const ComputedStyle* style) |
| 57 { |
| 58 RefPtr<ComputedStyle> newStyle = ComputedStyle::create(); |
| 59 |
| 60 // The marker always inherits from the list item, regardless of where it mig
ht end |
| 61 // up (e.g., in some deeply nested line box). See CSS3 spec. |
| 62 newStyle->inheritFrom(*parent.style()); |
| 63 if (style) { |
| 64 // Reuse the current margins. Otherwise resetting the margins to initial
values |
| 65 // would trigger unnecessary layout. |
| 66 newStyle->setMarginStart(style->marginStart()); |
| 67 newStyle->setMarginEnd(style->marginRight()); |
| 68 } |
| 69 return newStyle; |
| 70 } |
| 71 |
| 72 LayoutObject* MarkerPseudoElement::firstNonMarkerChild(LayoutObject* parent) |
| 73 { |
| 74 LayoutObject* result = parent->slowFirstChild(); |
| 75 while (result && result->isListMarker()) |
| 76 result = result->nextSibling(); |
| 77 return result; |
| 78 } |
| 79 |
| 80 LayoutObject* MarkerPseudoElement::createLayoutObject(const ComputedStyle& style
) |
| 81 { |
| 82 ASSERT(parentElement()->layoutObject()); |
| 83 return new LayoutListMarker(this, toLayoutListItem(parentElement()->layoutOb
ject())); |
| 84 } |
| 85 |
| 86 void MarkerPseudoElement::attachListMarker() |
| 87 { |
| 88 LayoutListItem* parentLayoutObject = toLayoutListItem(parentElement()->layou
tObject()); |
| 89 ASSERT(parentLayoutObject); |
| 90 ASSERT(layoutObject()); |
| 91 |
| 92 LayoutListMarker* marker = toLayoutListMarker(layoutObject()); |
| 93 parentLayoutObject->setMarker(marker); |
| 94 |
| 95 LayoutObject* markerParent = marker->parent(); |
| 96 |
| 97 LayoutObject* insertionLayoutObject = MarkerPseudoElement::parentOfFirstLine
Box(parentLayoutObject, marker); |
| 98 |
| 99 // We didn't find any line boxes so make the insertion point the LI layoutOb
ject. |
| 100 if (!insertionLayoutObject) |
| 101 insertionLayoutObject = parentLayoutObject; |
| 102 ASSERT(insertionLayoutObject); |
| 103 |
| 104 // Check if we're already inserted into the right parent as the first child. |
| 105 if (markerParent && marker == markerParent->slowFirstChild() |
| 106 && (markerParent == insertionLayoutObject || markerParent == insertionLa
youtObject->slowFirstChild())) |
| 107 return; |
| 108 |
| 109 marker->remove(); |
| 110 insertionLayoutObject->addChild(marker, MarkerPseudoElement::firstNonMarkerC
hild(insertionLayoutObject)); |
| 111 marker->updateMarginsAndContent(); |
| 112 |
| 113 // If markerParent is an anonymous block with no children, destroy it. |
| 114 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(marke
rParent)->firstChild() |
| 115 && !toLayoutBlock(markerParent)->continuation()) { |
| 116 markerParent->destroy(); |
| 117 } |
| 118 |
| 119 if (marker->isInside()) |
| 120 parentLayoutObject->containingBlock()->setPreferredLogicalWidthsDirty(); |
| 121 } |
| 122 |
| 123 void MarkerPseudoElement::attach(const AttachContext& context) |
| 124 { |
| 125 PseudoElement::attach(context); |
| 126 ASSERT(layoutObject()); |
| 127 |
| 128 LayoutObject* parent = layoutObject()->parent(); |
| 129 if (!parent) |
| 130 return; |
| 131 |
| 132 LayoutListMarker* marker = toLayoutListMarker(layoutObject()); |
| 133 |
| 134 RefPtr<ComputedStyle> newStyle = MarkerPseudoElement::styleForListMarker(*(m
arker->mutableListItem()), marker->style()); |
| 135 marker->setStyle(newStyle.release()); |
| 136 |
| 137 attachListMarker(); |
| 138 } |
| 139 |
| 140 void MarkerPseudoElement::didRecalcStyle(StyleRecalcChange) |
| 141 { |
| 142 attachListMarker(); |
| 143 } |
| 144 |
| 145 } // namespace blink |
OLD | NEW |