OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |