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

Side by Side Diff: third_party/WebKit/Source/core/dom/PseudoElement.cpp

Issue 2727853002: [css-display] Support display: contents pseudo-elements.
Patch Set: [css-display] Support display: contents pseudos. Created 3 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Neither the name of Google Inc. nor the names of its 10 * * Neither the name of Google Inc. nor the names of its
11 * contributors may be used to endorse or promote products derived from 11 * contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission. 12 * this software without specific prior written permission.
13 * 13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "core/dom/PseudoElement.h" 27 #include "core/dom/PseudoElement.h"
28 28
29 #include "core/dom/FirstLetterPseudoElement.h" 29 #include "core/dom/FirstLetterPseudoElement.h"
30 #include "core/dom/NodeComputedStyle.h"
30 #include "core/frame/UseCounter.h" 31 #include "core/frame/UseCounter.h"
31 #include "core/layout/LayoutObject.h" 32 #include "core/layout/LayoutObject.h"
32 #include "core/layout/LayoutQuote.h" 33 #include "core/layout/LayoutQuote.h"
33 #include "core/probe/CoreProbes.h" 34 #include "core/probe/CoreProbes.h"
34 #include "core/style/ContentData.h" 35 #include "core/style/ContentData.h"
35 36
36 namespace blink { 37 namespace blink {
37 38
38 PseudoElement* PseudoElement::create(Element* parent, PseudoId pseudoId) { 39 PseudoElement* PseudoElement::create(Element* parent, PseudoId pseudoId) {
39 return new PseudoElement(parent, pseudoId); 40 return new PseudoElement(parent, pseudoId);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 document().adoptIfNeeded(*this); 115 document().adoptIfNeeded(*this);
115 setParentOrShadowHostNode(0); 116 setParentOrShadowHostNode(0);
116 removedFrom(parent); 117 removedFrom(parent);
117 } 118 }
118 119
119 void PseudoElement::attachLayoutTree(const AttachContext& context) { 120 void PseudoElement::attachLayoutTree(const AttachContext& context) {
120 DCHECK(!layoutObject()); 121 DCHECK(!layoutObject());
121 122
122 Element::attachLayoutTree(context); 123 Element::attachLayoutTree(context);
123 124
124 LayoutObject* layoutObject = this->layoutObject(); 125 ComputedStyle* style = mutableComputedStyle();
125 if (!layoutObject) 126 if (!style || (style->styleType() != PseudoIdBefore &&
127 style->styleType() != PseudoIdAfter))
126 return; 128 return;
127 129
128 ComputedStyle& style = layoutObject->mutableStyleRef(); 130 DCHECK(style->contentData());
129 if (style.styleType() != PseudoIdBefore && style.styleType() != PseudoIdAfter)
130 return;
131 DCHECK(style.contentData());
132 131
133 for (const ContentData* content = style.contentData(); content; 132 LayoutObject* parentLayoutObject = layoutObject();
133 if (!parentLayoutObject)
134 parentLayoutObject = LayoutTreeBuilderTraversal::parentLayoutObject(*this);
135
136 for (const ContentData* content = style->contentData(); content;
134 content = content->next()) { 137 content = content->next()) {
135 LayoutObject* child = content->createLayoutObject(*this, style); 138 LayoutObject* child = content->createLayoutObject(*this, *style);
136 if (layoutObject->isChildAllowed(child, style)) { 139 if (parentLayoutObject->isChildAllowed(child, *style)) {
137 layoutObject->addChild(child); 140 parentLayoutObject->addChild(child);
141 DCHECK(child->isPseudoElementGeneratedContentFor(*this));
138 if (child->isQuote()) 142 if (child->isQuote())
139 toLayoutQuote(child)->attachQuote(); 143 toLayoutQuote(child)->attachQuote();
140 } else { 144 } else {
141 child->destroy(); 145 child->destroy();
142 } 146 }
143 } 147 }
144 } 148 }
145 149
146 bool PseudoElement::layoutObjectIsNeeded(const ComputedStyle& style) { 150 bool PseudoElement::layoutObjectIsNeeded(const ComputedStyle& style) {
147 return pseudoElementLayoutObjectIsNeeded(&style); 151 return pseudoElementLayoutObjectIsNeeded(&style);
148 } 152 }
149 153
154 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.
155 if (!layoutObject->isAnonymous())
156 return false;
157 return layoutObject->isText() || layoutObject->isQuote() ||
158 layoutObject->isImage();
159 }
160
161 static void updateGeneratedContentStyleIn(LayoutObject* root,
162 ComputedStyle* style) {
163 for (LayoutObject* child = root; child; child = child->nextInPreOrder(root)) {
164 if (isGeneratedContentLike(child))
165 child->setPseudoStyle(style);
166 }
167 }
168
150 void PseudoElement::didRecalcStyle() { 169 void PseudoElement::didRecalcStyle() {
151 if (!layoutObject())
152 return;
153
154 // The layoutObjects inside pseudo elements are anonymous so they don't get 170 // The layoutObjects inside pseudo elements are anonymous so they don't get
155 // notified of recalcStyle and must have the style propagated downward 171 // notified of recalcStyle and must have the style propagated downward
156 // manually similar to LayoutObject::propagateStyleToAnonymousChildren. 172 // manually similar to LayoutObject::propagateStyleToAnonymousChildren.
157 LayoutObject* layoutObject = this->layoutObject(); 173 if (LayoutObject* layoutObject = this->layoutObject()) {
158 for (LayoutObject* child = layoutObject->nextInPreOrder(layoutObject); child; 174 updateGeneratedContentStyleIn(layoutObject, layoutObject->mutableStyle());
159 child = child->nextInPreOrder(layoutObject)) { 175 } else if (hasDisplayContentsStyle()) {
160 // We only manage the style for the generated content items. 176 DCHECK(m_pseudoId == PseudoIdBefore || m_pseudoId == PseudoIdAfter);
161 if (!child->isText() && !child->isQuote() && !child->isImage())
162 continue;
163 177
164 child->setPseudoStyle(layoutObject->mutableStyle()); 178 LayoutObject* layoutParent =
179 LayoutTreeBuilderTraversal::parentLayoutObject(*this);
180 if (!layoutParent)
181 return;
182
183 const bool isBefore = m_pseudoId == PseudoIdBefore;
184 ComputedStyle* style = mutableComputedStyle();
185 LayoutObject* child = isBefore ? layoutParent->slowFirstChild()
186 : layoutParent->slowLastChild();
187
188 bool foundGeneratedContent = false;
189 while (child) {
190 bool isThisPseudoContent =
191 child->isPseudoElementGeneratedContentFor(*this);
192 if (isThisPseudoContent)
193 foundGeneratedContent = true;
194 else if (foundGeneratedContent)
195 break;
196
197 if (isThisPseudoContent) {
198 updateGeneratedContentStyleIn(child, style);
199 child = isBefore ? child->nextSibling() : child->previousSibling();
200 } else {
201 child = isBefore ? child->nextInPreOrder(layoutParent)
202 : 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'
203 }
204 }
205
206 DCHECK(foundGeneratedContent);
165 } 207 }
166 } 208 }
167 209
168 // With PseudoElements the DOM tree and Layout tree can differ. When you attach 210 // With PseudoElements the DOM tree and Layout tree can differ. When you attach
169 // a, first-letter for example, into the DOM we walk down the Layout 211 // a, first-letter for example, into the DOM we walk down the Layout
170 // tree to find the correct insertion point for the LayoutObject. But, this 212 // tree to find the correct insertion point for the LayoutObject. But, this
171 // means if we ask for the parentOrShadowHost Node from the first-letter 213 // means if we ask for the parentOrShadowHost Node from the first-letter
172 // pseudo element we will get some arbitrary ancestor of the LayoutObject. 214 // pseudo element we will get some arbitrary ancestor of the LayoutObject.
173 // 215 //
174 // For hit testing, we need the parent Node of the LayoutObject for the 216 // For hit testing, we need the parent Node of the LayoutObject for the
(...skipping 14 matching lines...) Expand all
189 LayoutObject* ancestor = layoutObject()->parent(); 231 LayoutObject* ancestor = layoutObject()->parent();
190 while (ancestor->isAnonymous() || 232 while (ancestor->isAnonymous() ||
191 (ancestor->node() && ancestor->node()->isPseudoElement())) { 233 (ancestor->node() && ancestor->node()->isPseudoElement())) {
192 DCHECK(ancestor->parent()); 234 DCHECK(ancestor->parent());
193 ancestor = ancestor->parent(); 235 ancestor = ancestor->parent();
194 } 236 }
195 return ancestor->node(); 237 return ancestor->node();
196 } 238 }
197 239
198 } // namespace blink 240 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698