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

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 3 years, 10 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
(...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) {
esprehn 2017/03/08 03:42:38 IIRC static implies inline, you don't need both li
emilio 2017/03/08 08:32:40 As far as I know, inline and static are not quite
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 return toElement(layoutObject->node())->isInTopLayer();
42 return true;
43 return false;
44 } 44 }
45 45
46 void ParentDetails::didTraverseInsertionPoint( 46 void LayoutTreeBuilderTraversal::ParentDetails::didTraverseInsertionPoint(
47 const InsertionPoint* insertionPoint) { 47 const InsertionPoint* insertionPoint) {
48 if (!m_insertionPoint) { 48 if (!m_insertionPoint) {
49 m_insertionPoint = insertionPoint; 49 m_insertionPoint = insertionPoint;
50 } 50 }
51 } 51 }
52 52
53 inline static void assertPseudoElementParent( 53 inline static void assertPseudoElementParent(
54 const PseudoElement& pseudoElement) { 54 const PseudoElement& pseudoElement) {
55 DCHECK(pseudoElement.parentNode()); 55 DCHECK(pseudoElement.parentNode());
56 DCHECK(pseudoElement.parentNode()->canParticipateInFlatTree()); 56 DCHECK(pseudoElement.parentNode()->canParticipateInFlatTree());
57 } 57 }
58 58
59 ContainerNode* parent(const Node& node, ParentDetails* details) { 59 ContainerNode* LayoutTreeBuilderTraversal::parent(const Node& node,
60 ParentDetails* details) {
60 // TODO(hayato): Uncomment this once we can be sure 61 // TODO(hayato): Uncomment this once we can be sure
61 // LayoutTreeBuilderTraversal::parent() is used only for a node which is 62 // LayoutTreeBuilderTraversal::parent() is used only for a node which is
62 // connected. 63 // connected.
63 // DCHECK(node.isConnected()); 64 // DCHECK(node.isConnected());
64 if (node.isPseudoElement()) { 65 if (node.isPseudoElement()) {
65 assertPseudoElementParent(toPseudoElement(node)); 66 assertPseudoElementParent(toPseudoElement(node));
66 return node.parentNode(); 67 return node.parentNode();
67 } 68 }
68 return FlatTreeTraversal::parent(node, details); 69 return FlatTreeTraversal::parent(node, details);
69 } 70 }
70 71
71 Node* nextSibling(const Node& node) { 72 ContainerNode* LayoutTreeBuilderTraversal::layoutParent(
73 const Node& node,
74 ParentDetails* details) {
75 ContainerNode* parent = LayoutTreeBuilderTraversal::parent(node, details);
76
77 while (parent && hasDisplayContentsStyle(*parent))
78 parent = LayoutTreeBuilderTraversal::parent(*parent, details);
79
80 return parent;
81 }
82
83 LayoutObject* LayoutTreeBuilderTraversal::parentLayoutObject(const Node& node) {
84 ContainerNode* parent = LayoutTreeBuilderTraversal::layoutParent(node);
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* sibling =
232 sibling && limit-- != 0; 269 nextSiblingLayoutObjectInternal(nextSibling(node), limit))
270 return sibling;
271
272 Node* parent = LayoutTreeBuilderTraversal::parent(node);
273 while (limit && parent && hasDisplayContentsStyle(*parent)) {
274 if (LayoutObject* sibling =
275 nextSiblingLayoutObjectInternal(nextSibling(*parent), limit))
276 return sibling;
277 parent = LayoutTreeBuilderTraversal::parent(*parent);
278 }
279
280 return nullptr;
281 }
282
283 static LayoutObject* previousSiblingLayoutObjectInternal(Node* node,
284 int32_t& limit) {
285 for (Node* sibling = node; sibling && limit-- != 0;
233 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) { 286 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) {
234 LayoutObject* layoutObject = sibling->layoutObject(); 287 LayoutObject* layoutObject = sibling->layoutObject();
288
289 #if DCHECK_IS_ON()
290 if (hasDisplayContentsStyle(*sibling))
291 DCHECK(!layoutObject);
292 #endif
293
294 if (!layoutObject && hasDisplayContentsStyle(*sibling)) {
295 layoutObject = previousSiblingLayoutObjectInternal(
296 pseudoAwareLastChild(*sibling), limit);
297 if (layoutObject)
298 return layoutObject;
299 if (!limit)
300 return nullptr;
301 }
302
235 if (layoutObject && !isLayoutObjectReparented(layoutObject)) 303 if (layoutObject && !isLayoutObjectReparented(layoutObject))
236 return layoutObject; 304 return layoutObject;
237 } 305 }
238 return 0; 306
307 return nullptr;
239 } 308 }
240 309
241 LayoutObject* nextInTopLayer(const Element& element) { 310 LayoutObject* LayoutTreeBuilderTraversal::previousSiblingLayoutObject(
311 const Node& node,
312 int32_t limit) {
313 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit;
314 if (LayoutObject* sibling =
315 previousSiblingLayoutObjectInternal(previousSibling(node), limit))
316 return sibling;
317
318 Node* parent = LayoutTreeBuilderTraversal::parent(node);
319 while (limit && parent && hasDisplayContentsStyle(*parent)) {
320 if (LayoutObject* sibling = previousSiblingLayoutObjectInternal(
321 previousSibling(*parent), limit))
322 return sibling;
323 parent = LayoutTreeBuilderTraversal::parent(*parent);
324 }
325
326 return nullptr;
327 }
328
329 LayoutObject* LayoutTreeBuilderTraversal::nextInTopLayer(
330 const Element& element) {
242 if (!element.isInTopLayer()) 331 if (!element.isInTopLayer())
243 return 0; 332 return 0;
244 const HeapVector<Member<Element>>& topLayerElements = 333 const HeapVector<Member<Element>>& topLayerElements =
245 element.document().topLayerElements(); 334 element.document().topLayerElements();
246 size_t position = topLayerElements.find(&element); 335 size_t position = topLayerElements.find(&element);
247 DCHECK_NE(position, kNotFound); 336 DCHECK_NE(position, kNotFound);
248 for (size_t i = position + 1; i < topLayerElements.size(); ++i) { 337 for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
249 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject()) 338 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject())
250 return layoutObject; 339 return layoutObject;
251 } 340 }
252 return 0; 341 return 0;
253 } 342 }
254 343
255 } // namespace LayoutTreeBuilderTraversal
256
257 } // namespace blink 344 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698