Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(704)

Unified Diff: Source/core/dom/MarkerPseudoElement.cpp

Issue 778003003: List marker pseudo elements. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698