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

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

Issue 2450093005: Support display: contents for elements, first-line and first-letter pseudos. (Closed)
Patch Set: Support display: contents for elements, first-line and first-letter pseudos. Created 4 years, 1 month 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
(...skipping 15 matching lines...) Expand all
26 26
27 #include "core/dom/LayoutTreeBuilderTraversal.h" 27 #include "core/dom/LayoutTreeBuilderTraversal.h"
28 28
29 #include "core/HTMLNames.h" 29 #include "core/HTMLNames.h"
30 #include "core/dom/PseudoElement.h" 30 #include "core/dom/PseudoElement.h"
31 #include "core/dom/shadow/FlatTreeTraversal.h" 31 #include "core/dom/shadow/FlatTreeTraversal.h"
32 #include "core/layout/LayoutObject.h" 32 #include "core/layout/LayoutObject.h"
33 33
34 namespace blink { 34 namespace blink {
35 35
36 namespace LayoutTreeBuilderTraversal { 36 inline static bool hasDisplayContentsStyle(const Node& node) {
37 return node.isElementNode() && toElement(node).hasDisplayContentsStyle();
38 }
37 39
38 static bool isLayoutObjectReparented(const LayoutObject* layoutObject) { 40 static bool isLayoutObjectReparented(const LayoutObject* layoutObject) {
39 if (!layoutObject->node()->isElementNode()) 41 if (!layoutObject->node()->isElementNode())
40 return false; 42 return false;
41 if (toElement(layoutObject->node())->isInTopLayer()) 43 if (toElement(layoutObject->node())->isInTopLayer())
42 return true; 44 return true;
45
46 // NB: We intentionally ignore display:contents children here, since we aim to
47 // find them in the traversal.
48
43 return false; 49 return false;
44 } 50 }
45 51
46 void ParentDetails::didTraverseInsertionPoint( 52 void LayoutTreeBuilderTraversal::ParentDetails::didTraverseInsertionPoint(
47 const InsertionPoint* insertionPoint) { 53 const InsertionPoint* insertionPoint) {
48 if (!m_insertionPoint) { 54 if (!m_insertionPoint) {
49 m_insertionPoint = insertionPoint; 55 m_insertionPoint = insertionPoint;
50 } 56 }
51 } 57 }
52 58
53 inline static void assertPseudoElementParent( 59 inline static void assertPseudoElementParent(
54 const PseudoElement& pseudoElement) { 60 const PseudoElement& pseudoElement) {
55 DCHECK(pseudoElement.parentNode()); 61 DCHECK(pseudoElement.parentNode());
56 DCHECK(pseudoElement.parentNode()->canParticipateInFlatTree()); 62 DCHECK(pseudoElement.parentNode()->canParticipateInFlatTree());
57 } 63 }
58 64
59 ContainerNode* parent(const Node& node, ParentDetails* details) { 65 ContainerNode* LayoutTreeBuilderTraversal::parent(const Node& node,
66 ParentDetails* details) {
60 // TODO(hayato): Uncomment this once we can be sure 67 // TODO(hayato): Uncomment this once we can be sure
61 // LayoutTreeBuilderTraversal::parent() is used only for a node which is 68 // LayoutTreeBuilderTraversal::parent() is used only for a node which is
62 // connected. 69 // connected.
63 // DCHECK(node.isConnected()); 70 // DCHECK(node.isConnected());
64 if (node.isPseudoElement()) { 71 if (node.isPseudoElement()) {
65 assertPseudoElementParent(toPseudoElement(node)); 72 assertPseudoElementParent(toPseudoElement(node));
66 return node.parentNode(); 73 return node.parentNode();
67 } 74 }
68 return FlatTreeTraversal::parent(node, details); 75 return FlatTreeTraversal::parent(node, details);
69 } 76 }
70 77
71 Node* nextSibling(const Node& node) { 78 LayoutObject* LayoutTreeBuilderTraversal::parentLayoutObject(const Node& node) {
79 ContainerNode* parent = LayoutTreeBuilderTraversal::parent(node);
80
81 while (parent && hasDisplayContentsStyle(*parent)) {
82 parent = LayoutTreeBuilderTraversal::parent(*parent);
83 }
rune 2016/11/08 13:26:49 You don't need the curly braces here.
emilio 2016/11/08 15:43:02 Acknowledged.
84
85 return parent ? parent->layoutObject() : nullptr;
86 }
87
88 Node* LayoutTreeBuilderTraversal::nextSibling(const Node& node) {
72 if (node.isBeforePseudoElement()) { 89 if (node.isBeforePseudoElement()) {
73 assertPseudoElementParent(toPseudoElement(node)); 90 assertPseudoElementParent(toPseudoElement(node));
74 if (Node* next = FlatTreeTraversal::firstChild(*node.parentNode())) 91 if (Node* next = FlatTreeTraversal::firstChild(*node.parentNode()))
75 return next; 92 return next;
76 } else { 93 } else {
77 if (node.isAfterPseudoElement()) 94 if (node.isAfterPseudoElement())
78 return nullptr; 95 return nullptr;
79 if (Node* next = FlatTreeTraversal::nextSibling(node)) 96 if (Node* next = FlatTreeTraversal::nextSibling(node))
80 return next; 97 return next;
81 } 98 }
82 99
83 Node* parent = FlatTreeTraversal::parent(node); 100 Node* parent = FlatTreeTraversal::parent(node);
84 if (parent && parent->isElementNode()) 101 if (parent && parent->isElementNode())
85 return toElement(parent)->pseudoElement(PseudoIdAfter); 102 return toElement(parent)->pseudoElement(PseudoIdAfter);
86 103
87 return nullptr; 104 return nullptr;
88 } 105 }
89 106
90 Node* previousSibling(const Node& node) { 107 Node* LayoutTreeBuilderTraversal::previousSibling(const Node& node) {
91 if (node.isAfterPseudoElement()) { 108 if (node.isAfterPseudoElement()) {
92 assertPseudoElementParent(toPseudoElement(node)); 109 assertPseudoElementParent(toPseudoElement(node));
93 if (Node* previous = FlatTreeTraversal::lastChild(*node.parentNode())) 110 if (Node* previous = FlatTreeTraversal::lastChild(*node.parentNode()))
94 return previous; 111 return previous;
95 } else { 112 } else {
96 if (node.isBeforePseudoElement()) 113 if (node.isBeforePseudoElement())
97 return nullptr; 114 return nullptr;
98 if (Node* previous = FlatTreeTraversal::previousSibling(node)) 115 if (Node* previous = FlatTreeTraversal::previousSibling(node))
99 return previous; 116 return previous;
100 } 117 }
101 118
102 Node* parent = FlatTreeTraversal::parent(node); 119 Node* parent = FlatTreeTraversal::parent(node);
103 if (parent && parent->isElementNode()) 120 if (parent && parent->isElementNode())
104 return toElement(parent)->pseudoElement(PseudoIdBefore); 121 return toElement(parent)->pseudoElement(PseudoIdBefore);
105 122
106 return nullptr; 123 return nullptr;
107 } 124 }
108 125
109 static Node* lastChild(const Node& node) { 126 static Node* lastChild(const Node& node) {
110 return FlatTreeTraversal::lastChild(node); 127 return FlatTreeTraversal::lastChild(node);
111 } 128 }
112 129
113 static Node* pseudoAwarePreviousSibling(const Node& node) { 130 static Node* pseudoAwarePreviousSibling(const Node& node) {
114 Node* previousNode = previousSibling(node); 131 Node* previousNode = LayoutTreeBuilderTraversal::previousSibling(node);
115 Node* parentNode = parent(node); 132 Node* parentNode = LayoutTreeBuilderTraversal::parent(node);
116 133
117 if (parentNode && parentNode->isElementNode() && !previousNode) { 134 if (parentNode && parentNode->isElementNode() && !previousNode) {
118 if (node.isAfterPseudoElement()) { 135 if (node.isAfterPseudoElement()) {
119 if (Node* child = lastChild(*parentNode)) 136 if (Node* child = lastChild(*parentNode))
120 return child; 137 return child;
121 } 138 }
122 if (!node.isBeforePseudoElement()) 139 if (!node.isBeforePseudoElement())
123 return toElement(parentNode)->pseudoElement(PseudoIdBefore); 140 return toElement(parentNode)->pseudoElement(PseudoIdBefore);
124 } 141 }
125 return previousNode; 142 return previousNode;
126 } 143 }
127 144
128 static Node* pseudoAwareLastChild(const Node& node) { 145 static Node* pseudoAwareLastChild(const Node& node) {
129 if (node.isElementNode()) { 146 if (node.isElementNode()) {
130 const Element& currentElement = toElement(node); 147 const Element& currentElement = toElement(node);
131 Node* last = currentElement.pseudoElement(PseudoIdAfter); 148 Node* last = currentElement.pseudoElement(PseudoIdAfter);
132 if (last) 149 if (last)
133 return last; 150 return last;
134 151
135 last = lastChild(currentElement); 152 last = lastChild(currentElement);
136 if (!last) 153 if (!last)
137 last = currentElement.pseudoElement(PseudoIdBefore); 154 last = currentElement.pseudoElement(PseudoIdBefore);
138 return last; 155 return last;
139 } 156 }
140 157
141 return lastChild(node); 158 return lastChild(node);
142 } 159 }
143 160
144 Node* previous(const Node& node, const Node* stayWithin) { 161 Node* LayoutTreeBuilderTraversal::previous(const Node& node,
162 const Node* stayWithin) {
145 if (node == stayWithin) 163 if (node == stayWithin)
146 return 0; 164 return 0;
147 165
148 if (Node* previousNode = pseudoAwarePreviousSibling(node)) { 166 if (Node* previousNode = pseudoAwarePreviousSibling(node)) {
149 while (Node* previousLastChild = pseudoAwareLastChild(*previousNode)) 167 while (Node* previousLastChild = pseudoAwareLastChild(*previousNode))
150 previousNode = previousLastChild; 168 previousNode = previousLastChild;
151 return previousNode; 169 return previousNode;
152 } 170 }
153 return parent(node); 171 return parent(node);
154 } 172 }
155 173
156 Node* firstChild(const Node& node) { 174 Node* LayoutTreeBuilderTraversal::firstChild(const Node& node) {
157 return FlatTreeTraversal::firstChild(node); 175 return FlatTreeTraversal::firstChild(node);
158 } 176 }
159 177
160 static Node* pseudoAwareNextSibling(const Node& node) { 178 static Node* pseudoAwareNextSibling(const Node& node) {
161 Node* parentNode = parent(node); 179 Node* parentNode = LayoutTreeBuilderTraversal::parent(node);
162 Node* nextNode = nextSibling(node); 180 Node* nextNode = LayoutTreeBuilderTraversal::nextSibling(node);
163 181
164 if (parentNode && parentNode->isElementNode() && !nextNode) { 182 if (parentNode && parentNode->isElementNode() && !nextNode) {
165 if (node.isBeforePseudoElement()) { 183 if (node.isBeforePseudoElement()) {
166 if (Node* child = firstChild(*parentNode)) 184 if (Node* child = LayoutTreeBuilderTraversal::firstChild(*parentNode))
167 return child; 185 return child;
168 } 186 }
169 if (!node.isAfterPseudoElement()) 187 if (!node.isAfterPseudoElement())
170 return toElement(parentNode)->pseudoElement(PseudoIdAfter); 188 return toElement(parentNode)->pseudoElement(PseudoIdAfter);
171 } 189 }
172 return nextNode; 190 return nextNode;
173 } 191 }
174 192
175 static Node* pseudoAwareFirstChild(const Node& node) { 193 static Node* pseudoAwareFirstChild(const Node& node) {
176 if (node.isElementNode()) { 194 if (node.isElementNode()) {
177 const Element& currentElement = toElement(node); 195 const Element& currentElement = toElement(node);
178 Node* first = currentElement.pseudoElement(PseudoIdBefore); 196 Node* first = currentElement.pseudoElement(PseudoIdBefore);
179 if (first) 197 if (first)
180 return first; 198 return first;
181 first = firstChild(currentElement); 199 first = LayoutTreeBuilderTraversal::firstChild(currentElement);
182 if (!first) 200 if (!first)
183 first = currentElement.pseudoElement(PseudoIdAfter); 201 first = currentElement.pseudoElement(PseudoIdAfter);
184 return first; 202 return first;
185 } 203 }
186 204
187 return firstChild(node); 205 return LayoutTreeBuilderTraversal::firstChild(node);
188 } 206 }
189 207
190 static Node* nextAncestorSibling(const Node& node, const Node* stayWithin) { 208 static Node* nextAncestorSibling(const Node& node, const Node* stayWithin) {
191 DCHECK(!pseudoAwareNextSibling(node)); 209 DCHECK(!pseudoAwareNextSibling(node));
192 DCHECK_NE(node, stayWithin); 210 DCHECK_NE(node, stayWithin);
193 for (Node* parentNode = parent(node); parentNode; 211 for (Node* parentNode = LayoutTreeBuilderTraversal::parent(node); parentNode;
194 parentNode = parent(*parentNode)) { 212 parentNode = LayoutTreeBuilderTraversal::parent(*parentNode)) {
195 if (parentNode == stayWithin) 213 if (parentNode == stayWithin)
196 return 0; 214 return 0;
197 if (Node* nextNode = pseudoAwareNextSibling(*parentNode)) 215 if (Node* nextNode = pseudoAwareNextSibling(*parentNode))
198 return nextNode; 216 return nextNode;
199 } 217 }
200 return 0; 218 return 0;
201 } 219 }
202 220
203 Node* nextSkippingChildren(const Node& node, const Node* stayWithin) { 221 Node* LayoutTreeBuilderTraversal::nextSkippingChildren(const Node& node,
222 const Node* stayWithin) {
204 if (node == stayWithin) 223 if (node == stayWithin)
205 return 0; 224 return 0;
206 if (Node* nextNode = pseudoAwareNextSibling(node)) 225 if (Node* nextNode = pseudoAwareNextSibling(node))
207 return nextNode; 226 return nextNode;
208 return nextAncestorSibling(node, stayWithin); 227 return nextAncestorSibling(node, stayWithin);
209 } 228 }
210 229
211 Node* next(const Node& node, const Node* stayWithin) { 230 Node* LayoutTreeBuilderTraversal::next(const Node& node,
231 const Node* stayWithin) {
212 if (Node* child = pseudoAwareFirstChild(node)) 232 if (Node* child = pseudoAwareFirstChild(node))
213 return child; 233 return child;
214 return nextSkippingChildren(node, stayWithin); 234 return nextSkippingChildren(node, stayWithin);
215 } 235 }
216 236
217 LayoutObject* nextSiblingLayoutObject(const Node& node, int32_t limit) { 237 static LayoutObject* nextSiblingLayoutObjectInternal(Node* node,
218 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; 238 int32_t& limit) {
219 for (Node* sibling = LayoutTreeBuilderTraversal::nextSibling(node); 239 for (Node* sibling = node; sibling && limit-- != 0;
220 sibling && limit-- != 0;
221 sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) { 240 sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) {
222 LayoutObject* layoutObject = sibling->layoutObject(); 241 LayoutObject* layoutObject = sibling->layoutObject();
242
243 #if DCHECK_IS_ON()
244 if (hasDisplayContentsStyle(*sibling))
245 DCHECK(!layoutObject);
246 #endif
247
248 if (!layoutObject && hasDisplayContentsStyle(*sibling)) {
249 layoutObject = nextSiblingLayoutObjectInternal(
250 pseudoAwareFirstChild(*sibling), limit);
251 if (layoutObject)
252 return layoutObject;
253 if (!limit)
254 return nullptr;
255 }
256
223 if (layoutObject && !isLayoutObjectReparented(layoutObject)) 257 if (layoutObject && !isLayoutObjectReparented(layoutObject))
224 return layoutObject; 258 return layoutObject;
225 } 259 }
226 return 0; 260
261 return nullptr;
227 } 262 }
228 263
229 LayoutObject* previousSiblingLayoutObject(const Node& node, int32_t limit) { 264 LayoutObject* LayoutTreeBuilderTraversal::nextSiblingLayoutObject(
265 const Node& node,
266 int32_t limit) {
230 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; 267 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit;
231 for (Node* sibling = LayoutTreeBuilderTraversal::previousSibling(node); 268 if (LayoutObject* foundLayoutObject = nextSiblingLayoutObjectInternal(
232 sibling && limit-- != 0; 269 LayoutTreeBuilderTraversal::nextSibling(node), limit))
270 return foundLayoutObject;
271
272 Node* parent = LayoutTreeBuilderTraversal::parent(node);
273 while (limit && parent && hasDisplayContentsStyle(*parent)) {
274 Node* sibling = LayoutTreeBuilderTraversal::nextSibling(*parent);
275 if (LayoutObject* siblingLayoutObject =
276 nextSiblingLayoutObjectInternal(sibling, limit))
277 return siblingLayoutObject;
278 parent = LayoutTreeBuilderTraversal::parent(*parent);
279 }
280
281 return nullptr;
282 }
283
284 static LayoutObject* previousSiblingLayoutObjectInternal(Node* node,
285 int32_t& limit) {
286 for (Node* sibling = node; sibling && limit-- != 0;
233 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) { 287 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) {
234 LayoutObject* layoutObject = sibling->layoutObject(); 288 LayoutObject* layoutObject = sibling->layoutObject();
289
290 #if DCHECK_IS_ON()
291 if (hasDisplayContentsStyle(*sibling))
292 DCHECK(!layoutObject);
293 #endif
294
295 if (!layoutObject && hasDisplayContentsStyle(*sibling)) {
296 layoutObject = previousSiblingLayoutObjectInternal(
297 pseudoAwareLastChild(*sibling), limit);
298 if (layoutObject)
299 return layoutObject;
300 if (!limit)
301 return nullptr;
302 }
303
235 if (layoutObject && !isLayoutObjectReparented(layoutObject)) 304 if (layoutObject && !isLayoutObjectReparented(layoutObject))
236 return layoutObject; 305 return layoutObject;
237 } 306 }
238 return 0; 307
308 return nullptr;
239 } 309 }
240 310
241 LayoutObject* nextInTopLayer(const Element& element) { 311 LayoutObject* LayoutTreeBuilderTraversal::previousSiblingLayoutObject(
312 const Node& node,
313 int32_t limit) {
314 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit;
315 if (LayoutObject* foundLayoutObject = previousSiblingLayoutObjectInternal(
316 LayoutTreeBuilderTraversal::previousSibling(node), limit))
317 return foundLayoutObject;
318
319 Node* parent = LayoutTreeBuilderTraversal::parent(node);
320 while (limit && parent && hasDisplayContentsStyle(*parent)) {
321 Node* displayContentsSibling =
322 LayoutTreeBuilderTraversal::previousSibling(*parent);
323 if (LayoutObject* siblingLayoutObject =
324 previousSiblingLayoutObjectInternal(displayContentsSibling, limit))
325 return siblingLayoutObject;
326 parent = LayoutTreeBuilderTraversal::parent(*parent);
327 }
328
329 return nullptr;
330 }
331
332 LayoutObject* LayoutTreeBuilderTraversal::nextInTopLayer(
333 const Element& element) {
242 if (!element.isInTopLayer()) 334 if (!element.isInTopLayer())
243 return 0; 335 return 0;
244 const HeapVector<Member<Element>>& topLayerElements = 336 const HeapVector<Member<Element>>& topLayerElements =
245 element.document().topLayerElements(); 337 element.document().topLayerElements();
246 size_t position = topLayerElements.find(&element); 338 size_t position = topLayerElements.find(&element);
247 DCHECK_NE(position, kNotFound); 339 DCHECK_NE(position, kNotFound);
248 for (size_t i = position + 1; i < topLayerElements.size(); ++i) { 340 for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
249 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject()) 341 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject())
250 return layoutObject; 342 return layoutObject;
251 } 343 }
252 return 0; 344 return 0;
253 } 345 }
254 346
255 } // namespace LayoutTreeBuilderTraversal
256
257 } // namespace blink 347 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698