Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/PseudoElement.cpp |
| diff --git a/third_party/WebKit/Source/core/dom/PseudoElement.cpp b/third_party/WebKit/Source/core/dom/PseudoElement.cpp |
| index 02b89a54b169f147c2a60c54cb20da313e7c778a..4d282aa87bb1ff0e59d3a6d94316b9c4ff661749 100644 |
| --- a/third_party/WebKit/Source/core/dom/PseudoElement.cpp |
| +++ b/third_party/WebKit/Source/core/dom/PseudoElement.cpp |
| @@ -27,6 +27,7 @@ |
| #include "core/dom/PseudoElement.h" |
| #include "core/dom/FirstLetterPseudoElement.h" |
| +#include "core/dom/NodeComputedStyle.h" |
| #include "core/frame/UseCounter.h" |
| #include "core/layout/LayoutObject.h" |
| #include "core/layout/LayoutQuote.h" |
| @@ -121,20 +122,23 @@ void PseudoElement::attachLayoutTree(const AttachContext& context) { |
| Element::attachLayoutTree(context); |
| - LayoutObject* layoutObject = this->layoutObject(); |
| - if (!layoutObject) |
| + ComputedStyle* style = mutableComputedStyle(); |
| + if (!style || (style->styleType() != PseudoIdBefore && |
| + style->styleType() != PseudoIdAfter)) |
| return; |
| - ComputedStyle& style = layoutObject->mutableStyleRef(); |
| - if (style.styleType() != PseudoIdBefore && style.styleType() != PseudoIdAfter) |
| - return; |
| - DCHECK(style.contentData()); |
| + DCHECK(style->contentData()); |
| + |
| + LayoutObject* parentLayoutObject = layoutObject(); |
| + if (!parentLayoutObject) |
| + parentLayoutObject = LayoutTreeBuilderTraversal::parentLayoutObject(*this); |
| - for (const ContentData* content = style.contentData(); content; |
| + for (const ContentData* content = style->contentData(); content; |
| content = content->next()) { |
| - LayoutObject* child = content->createLayoutObject(*this, style); |
| - if (layoutObject->isChildAllowed(child, style)) { |
| - layoutObject->addChild(child); |
| + LayoutObject* child = content->createLayoutObject(*this, *style); |
| + if (parentLayoutObject->isChildAllowed(child, *style)) { |
| + parentLayoutObject->addChild(child); |
| + DCHECK(child->isPseudoElementGeneratedContentFor(*this)); |
| if (child->isQuote()) |
| toLayoutQuote(child)->attachQuote(); |
| } else { |
| @@ -147,21 +151,59 @@ bool PseudoElement::layoutObjectIsNeeded(const ComputedStyle& style) { |
| return pseudoElementLayoutObjectIsNeeded(&style); |
| } |
| -void PseudoElement::didRecalcStyle() { |
| - if (!layoutObject()) |
| - return; |
| +static bool isGeneratedContentLike(LayoutObject* layoutObject) { |
|
rune
2017/04/04 14:23:41
Why not call it isGeneratedContent?
emilio
2017/04/04 15:09:18
Sounds good to me, yeah.
|
| + if (!layoutObject->isAnonymous()) |
| + return false; |
| + return layoutObject->isText() || layoutObject->isQuote() || |
| + layoutObject->isImage(); |
| +} |
| +static void updateGeneratedContentStyleIn(LayoutObject* root, |
| + ComputedStyle* style) { |
| + for (LayoutObject* child = root; child; child = child->nextInPreOrder(root)) { |
| + if (isGeneratedContentLike(child)) |
| + child->setPseudoStyle(style); |
| + } |
| +} |
| + |
| +void PseudoElement::didRecalcStyle() { |
| // The layoutObjects inside pseudo elements are anonymous so they don't get |
| // notified of recalcStyle and must have the style propagated downward |
| // manually similar to LayoutObject::propagateStyleToAnonymousChildren. |
| - LayoutObject* layoutObject = this->layoutObject(); |
| - for (LayoutObject* child = layoutObject->nextInPreOrder(layoutObject); child; |
| - child = child->nextInPreOrder(layoutObject)) { |
| - // We only manage the style for the generated content items. |
| - if (!child->isText() && !child->isQuote() && !child->isImage()) |
| - continue; |
| - |
| - child->setPseudoStyle(layoutObject->mutableStyle()); |
| + if (LayoutObject* layoutObject = this->layoutObject()) { |
| + updateGeneratedContentStyleIn(layoutObject, layoutObject->mutableStyle()); |
| + } else if (hasDisplayContentsStyle()) { |
| + DCHECK(m_pseudoId == PseudoIdBefore || m_pseudoId == PseudoIdAfter); |
| + |
| + LayoutObject* layoutParent = |
| + LayoutTreeBuilderTraversal::parentLayoutObject(*this); |
| + if (!layoutParent) |
| + return; |
| + |
| + const bool isBefore = m_pseudoId == PseudoIdBefore; |
| + ComputedStyle* style = mutableComputedStyle(); |
| + LayoutObject* child = isBefore ? layoutParent->slowFirstChild() |
| + : layoutParent->slowLastChild(); |
| + |
| + bool foundGeneratedContent = false; |
| + while (child) { |
| + bool isThisPseudoContent = |
| + child->isPseudoElementGeneratedContentFor(*this); |
| + if (isThisPseudoContent) |
| + foundGeneratedContent = true; |
| + else if (foundGeneratedContent) |
| + break; |
| + |
| + if (isThisPseudoContent) { |
| + updateGeneratedContentStyleIn(child, style); |
| + child = isBefore ? child->nextSibling() : child->previousSibling(); |
| + } else { |
| + child = isBefore ? child->nextInPreOrder(layoutParent) |
| + : child->previousInPreOrder(layoutParent); |
|
rune
2017/04/04 14:23:41
Why do you need to to walk descendants here?
In g
emilio
2017/04/04 15:09:18
The idea is to handle them, yeah. Right now I don'
|
| + } |
| + } |
| + |
| + DCHECK(foundGeneratedContent); |
| } |
| } |