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

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

Issue 2727853002: [css-display] Support display: contents pseudo-elements.
Patch Set: Add missing nullcheck (whoops). Created 3 years, 9 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/inspector/InspectorInstrumentation.h" 32 #include "core/inspector/InspectorInstrumentation.h"
32 #include "core/layout/LayoutObject.h" 33 #include "core/layout/LayoutObject.h"
33 #include "core/layout/LayoutQuote.h" 34 #include "core/layout/LayoutQuote.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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 parent->treeScope().adoptIfNeeded(*this); 91 parent->treeScope().adoptIfNeeded(*this);
91 setParentOrShadowHostNode(parent); 92 setParentOrShadowHostNode(parent);
92 setHasCustomStyleCallbacks(); 93 setHasCustomStyleCallbacks();
93 if ((pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter) && 94 if ((pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter) &&
94 parent->hasTagName(HTMLNames::inputTag)) 95 parent->hasTagName(HTMLNames::inputTag))
95 UseCounter::count(parent->document(), 96 UseCounter::count(parent->document(),
96 UseCounter::PseudoBeforeAfterForInputElement); 97 UseCounter::PseudoBeforeAfterForInputElement);
97 } 98 }
98 99
99 PassRefPtr<ComputedStyle> PseudoElement::customStyleForLayoutObject() { 100 PassRefPtr<ComputedStyle> PseudoElement::customStyleForLayoutObject() {
100 return parentOrShadowHostElement()->layoutObject()->getCachedPseudoStyle( 101 return parentOrShadowHostElement()->pseudoStyle(m_pseudoId);
101 m_pseudoId);
102 } 102 }
103 103
104 void PseudoElement::dispose() { 104 void PseudoElement::dispose() {
105 DCHECK(parentOrShadowHostElement()); 105 DCHECK(parentOrShadowHostElement());
106 106
107 probe::pseudoElementDestroyed(this); 107 probe::pseudoElementDestroyed(this);
108 108
109 DCHECK(!nextSibling()); 109 DCHECK(!nextSibling());
110 DCHECK(!previousSibling()); 110 DCHECK(!previousSibling());
111 111
112 detachLayoutTree(); 112 detachLayoutTree();
113 Element* parent = parentOrShadowHostElement(); 113 Element* parent = parentOrShadowHostElement();
114 document().adoptIfNeeded(*this); 114 document().adoptIfNeeded(*this);
115 setParentOrShadowHostNode(0); 115 setParentOrShadowHostNode(0);
116 removedFrom(parent); 116 removedFrom(parent);
117 } 117 }
118 118
119 void PseudoElement::attachLayoutTree(const AttachContext& context) { 119 void PseudoElement::attachLayoutTree(const AttachContext& context) {
120 DCHECK(!layoutObject()); 120 DCHECK(!layoutObject());
121 121
122 Element::attachLayoutTree(context); 122 Element::attachLayoutTree(context);
123 123
124 LayoutObject* layoutObject = this->layoutObject(); 124 ComputedStyle* style = mutableComputedStyle();
125 if (!layoutObject) 125 if (!style || (style->styleType() != PseudoIdBefore &&
126 style->styleType() != PseudoIdAfter))
126 return; 127 return;
127 128
128 ComputedStyle& style = layoutObject->mutableStyleRef(); 129 DCHECK(style->contentData());
129 if (style.styleType() != PseudoIdBefore && style.styleType() != PseudoIdAfter)
130 return;
131 DCHECK(style.contentData());
132 130
133 for (const ContentData* content = style.contentData(); content; 131 LayoutObject* parentLayoutObject = layoutObject();
132 if (!parentLayoutObject)
133 parentLayoutObject = LayoutTreeBuilderTraversal::parentLayoutObject(*this);
134
135 for (const ContentData* content = style->contentData(); content;
134 content = content->next()) { 136 content = content->next()) {
135 LayoutObject* child = content->createLayoutObject(document(), style); 137 LayoutObject* child = content->createLayoutObject(*this, *style);
136 if (layoutObject->isChildAllowed(child, style)) { 138 if (parentLayoutObject->isChildAllowed(child, *style)) {
137 layoutObject->addChild(child); 139 parentLayoutObject->addChild(child);
140 DCHECK(child->isPseudoElementGeneratedContentFor(*this));
138 if (child->isQuote()) 141 if (child->isQuote())
139 toLayoutQuote(child)->attachQuote(); 142 toLayoutQuote(child)->attachQuote();
140 } else { 143 } else {
141 child->destroy(); 144 child->destroy();
142 } 145 }
143 } 146 }
144 } 147 }
145 148
149 void PseudoElement::detachLayoutTree(const AttachContext& context) {
150 Element::detachLayoutTree(context);
151 }
152
146 bool PseudoElement::layoutObjectIsNeeded(const ComputedStyle& style) { 153 bool PseudoElement::layoutObjectIsNeeded(const ComputedStyle& style) {
147 return pseudoElementLayoutObjectIsNeeded(&style); 154 return pseudoElementLayoutObjectIsNeeded(&style);
148 } 155 }
149 156
157 static bool isGeneratedContentLike(LayoutObject* layoutObject) {
158 if (!layoutObject->isAnonymous())
159 return false;
160 return layoutObject->isText() || layoutObject->isQuote() ||
161 layoutObject->isImage();
162 }
163
164 static void updateGeneratedContentStyleIn(LayoutObject* root,
165 ComputedStyle* style) {
166 for (LayoutObject* child = root; child; child = child->nextInPreOrder(root)) {
167 if (isGeneratedContentLike(child))
168 child->setPseudoStyle(style);
169 }
170 }
171
150 void PseudoElement::didRecalcStyle() { 172 void PseudoElement::didRecalcStyle() {
151 if (!layoutObject())
152 return;
153
154 // The layoutObjects inside pseudo elements are anonymous so they don't get 173 // The layoutObjects inside pseudo elements are anonymous so they don't get
155 // notified of recalcStyle and must have the style propagated downward 174 // notified of recalcStyle and must have the style propagated downward
156 // manually similar to LayoutObject::propagateStyleToAnonymousChildren. 175 // manually similar to LayoutObject::propagateStyleToAnonymousChildren.
157 LayoutObject* layoutObject = this->layoutObject(); 176 if (LayoutObject* layoutObject = this->layoutObject()) {
158 for (LayoutObject* child = layoutObject->nextInPreOrder(layoutObject); child; 177 updateGeneratedContentStyleIn(layoutObject, layoutObject->mutableStyle());
159 child = child->nextInPreOrder(layoutObject)) { 178 } else if (hasDisplayContentsStyle()) {
160 // We only manage the style for the generated content items. 179 DCHECK(m_pseudoId == PseudoIdBefore || m_pseudoId == PseudoIdAfter);
161 if (!child->isText() && !child->isQuote() && !child->isImage())
162 continue;
163 180
164 child->setPseudoStyle(layoutObject->mutableStyle()); 181 LayoutObject* layoutParent =
182 LayoutTreeBuilderTraversal::parentLayoutObject(*this);
183 if (!layoutParent)
184 return;
185
186 const bool isBefore = m_pseudoId == PseudoIdBefore;
187 ComputedStyle* style = mutableComputedStyle();
188 LayoutObject* child = isBefore ? layoutParent->slowFirstChild()
189 : layoutParent->slowLastChild();
190
191 bool foundGeneratedContent = false;
192 while (child) {
193 bool isThisPseudoContent =
194 child->isPseudoElementGeneratedContentFor(*this);
195 if (isThisPseudoContent)
196 foundGeneratedContent = true;
197 else if (foundGeneratedContent)
198 break;
199
200 if (isThisPseudoContent) {
201 updateGeneratedContentStyleIn(child, style);
202 child = isBefore ? child->nextSibling() : child->previousSibling();
203 } else {
204 child = isBefore ? child->nextInPreOrder(layoutParent)
205 : child->previousInPreOrder(layoutParent);
206 }
207 }
208
209 DCHECK(foundGeneratedContent);
165 } 210 }
166 } 211 }
167 212
168 // With PseudoElements the DOM tree and Layout tree can differ. When you attach 213 // 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 214 // 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 215 // 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 216 // means if we ask for the parentOrShadowHost Node from the first-letter
172 // pseudo element we will get some arbitrary ancestor of the LayoutObject. 217 // pseudo element we will get some arbitrary ancestor of the LayoutObject.
173 // 218 //
174 // For hit testing, we need the parent Node of the LayoutObject for the 219 // For hit testing, we need the parent Node of the LayoutObject for the
(...skipping 14 matching lines...) Expand all
189 LayoutObject* ancestor = layoutObject()->parent(); 234 LayoutObject* ancestor = layoutObject()->parent();
190 while (ancestor->isAnonymous() || 235 while (ancestor->isAnonymous() ||
191 (ancestor->node() && ancestor->node()->isPseudoElement())) { 236 (ancestor->node() && ancestor->node()->isPseudoElement())) {
192 DCHECK(ancestor->parent()); 237 DCHECK(ancestor->parent());
193 ancestor = ancestor->parent(); 238 ancestor = ancestor->parent();
194 } 239 }
195 return ancestor->node(); 240 return ancestor->node();
196 } 241 }
197 242
198 } // namespace blink 243 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698