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

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 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 LayoutObject* LayoutTreeBuilderTraversal::parentLayoutObject(const Node& node) {
73 ContainerNode* parent = LayoutTreeBuilderTraversal::parent(node);
74
75 while (parent && hasDisplayContentsStyle(*parent))
76 parent = LayoutTreeBuilderTraversal::parent(*parent);
77
78 return parent ? parent->layoutObject() : nullptr;
79 }
80
81 Node* LayoutTreeBuilderTraversal::nextSibling(const Node& node) {
72 if (node.isBeforePseudoElement()) { 82 if (node.isBeforePseudoElement()) {
73 assertPseudoElementParent(toPseudoElement(node)); 83 assertPseudoElementParent(toPseudoElement(node));
74 if (Node* next = FlatTreeTraversal::firstChild(*node.parentNode())) 84 if (Node* next = FlatTreeTraversal::firstChild(*node.parentNode()))
75 return next; 85 return next;
76 } else { 86 } else {
77 if (node.isAfterPseudoElement()) 87 if (node.isAfterPseudoElement())
78 return nullptr; 88 return nullptr;
79 if (Node* next = FlatTreeTraversal::nextSibling(node)) 89 if (Node* next = FlatTreeTraversal::nextSibling(node))
80 return next; 90 return next;
81 } 91 }
82 92
83 Node* parent = FlatTreeTraversal::parent(node); 93 Node* parent = FlatTreeTraversal::parent(node);
84 if (parent && parent->isElementNode()) 94 if (parent && parent->isElementNode())
85 return toElement(parent)->pseudoElement(PseudoIdAfter); 95 return toElement(parent)->pseudoElement(PseudoIdAfter);
86 96
87 return nullptr; 97 return nullptr;
88 } 98 }
89 99
90 Node* previousSibling(const Node& node) { 100 Node* LayoutTreeBuilderTraversal::previousSibling(const Node& node) {
91 if (node.isAfterPseudoElement()) { 101 if (node.isAfterPseudoElement()) {
92 assertPseudoElementParent(toPseudoElement(node)); 102 assertPseudoElementParent(toPseudoElement(node));
93 if (Node* previous = FlatTreeTraversal::lastChild(*node.parentNode())) 103 if (Node* previous = FlatTreeTraversal::lastChild(*node.parentNode()))
94 return previous; 104 return previous;
95 } else { 105 } else {
96 if (node.isBeforePseudoElement()) 106 if (node.isBeforePseudoElement())
97 return nullptr; 107 return nullptr;
98 if (Node* previous = FlatTreeTraversal::previousSibling(node)) 108 if (Node* previous = FlatTreeTraversal::previousSibling(node))
99 return previous; 109 return previous;
100 } 110 }
101 111
102 Node* parent = FlatTreeTraversal::parent(node); 112 Node* parent = FlatTreeTraversal::parent(node);
103 if (parent && parent->isElementNode()) 113 if (parent && parent->isElementNode())
104 return toElement(parent)->pseudoElement(PseudoIdBefore); 114 return toElement(parent)->pseudoElement(PseudoIdBefore);
105 115
106 return nullptr; 116 return nullptr;
107 } 117 }
108 118
109 static Node* lastChild(const Node& node) { 119 static Node* lastChild(const Node& node) {
110 return FlatTreeTraversal::lastChild(node); 120 return FlatTreeTraversal::lastChild(node);
111 } 121 }
112 122
113 static Node* pseudoAwarePreviousSibling(const Node& node) { 123 static Node* pseudoAwarePreviousSibling(const Node& node) {
114 Node* previousNode = previousSibling(node); 124 Node* previousNode = LayoutTreeBuilderTraversal::previousSibling(node);
115 Node* parentNode = parent(node); 125 Node* parentNode = LayoutTreeBuilderTraversal::parent(node);
116 126
117 if (parentNode && parentNode->isElementNode() && !previousNode) { 127 if (parentNode && parentNode->isElementNode() && !previousNode) {
118 if (node.isAfterPseudoElement()) { 128 if (node.isAfterPseudoElement()) {
119 if (Node* child = lastChild(*parentNode)) 129 if (Node* child = lastChild(*parentNode))
120 return child; 130 return child;
121 } 131 }
122 if (!node.isBeforePseudoElement()) 132 if (!node.isBeforePseudoElement())
123 return toElement(parentNode)->pseudoElement(PseudoIdBefore); 133 return toElement(parentNode)->pseudoElement(PseudoIdBefore);
124 } 134 }
125 return previousNode; 135 return previousNode;
126 } 136 }
127 137
128 static Node* pseudoAwareLastChild(const Node& node) { 138 static Node* pseudoAwareLastChild(const Node& node) {
129 if (node.isElementNode()) { 139 if (node.isElementNode()) {
130 const Element& currentElement = toElement(node); 140 const Element& currentElement = toElement(node);
131 Node* last = currentElement.pseudoElement(PseudoIdAfter); 141 Node* last = currentElement.pseudoElement(PseudoIdAfter);
132 if (last) 142 if (last)
133 return last; 143 return last;
134 144
135 last = lastChild(currentElement); 145 last = lastChild(currentElement);
136 if (!last) 146 if (!last)
137 last = currentElement.pseudoElement(PseudoIdBefore); 147 last = currentElement.pseudoElement(PseudoIdBefore);
138 return last; 148 return last;
139 } 149 }
140 150
141 return lastChild(node); 151 return lastChild(node);
142 } 152 }
143 153
144 Node* previous(const Node& node, const Node* stayWithin) { 154 Node* LayoutTreeBuilderTraversal::previous(const Node& node,
155 const Node* stayWithin) {
145 if (node == stayWithin) 156 if (node == stayWithin)
146 return 0; 157 return 0;
147 158
148 if (Node* previousNode = pseudoAwarePreviousSibling(node)) { 159 if (Node* previousNode = pseudoAwarePreviousSibling(node)) {
149 while (Node* previousLastChild = pseudoAwareLastChild(*previousNode)) 160 while (Node* previousLastChild = pseudoAwareLastChild(*previousNode))
150 previousNode = previousLastChild; 161 previousNode = previousLastChild;
151 return previousNode; 162 return previousNode;
152 } 163 }
153 return parent(node); 164 return parent(node);
154 } 165 }
155 166
156 Node* firstChild(const Node& node) { 167 Node* LayoutTreeBuilderTraversal::firstChild(const Node& node) {
157 return FlatTreeTraversal::firstChild(node); 168 return FlatTreeTraversal::firstChild(node);
158 } 169 }
159 170
160 static Node* pseudoAwareNextSibling(const Node& node) { 171 static Node* pseudoAwareNextSibling(const Node& node) {
161 Node* parentNode = parent(node); 172 Node* parentNode = LayoutTreeBuilderTraversal::parent(node);
162 Node* nextNode = nextSibling(node); 173 Node* nextNode = LayoutTreeBuilderTraversal::nextSibling(node);
163 174
164 if (parentNode && parentNode->isElementNode() && !nextNode) { 175 if (parentNode && parentNode->isElementNode() && !nextNode) {
165 if (node.isBeforePseudoElement()) { 176 if (node.isBeforePseudoElement()) {
166 if (Node* child = firstChild(*parentNode)) 177 if (Node* child = LayoutTreeBuilderTraversal::firstChild(*parentNode))
167 return child; 178 return child;
168 } 179 }
169 if (!node.isAfterPseudoElement()) 180 if (!node.isAfterPseudoElement())
170 return toElement(parentNode)->pseudoElement(PseudoIdAfter); 181 return toElement(parentNode)->pseudoElement(PseudoIdAfter);
171 } 182 }
172 return nextNode; 183 return nextNode;
173 } 184 }
174 185
175 static Node* pseudoAwareFirstChild(const Node& node) { 186 static Node* pseudoAwareFirstChild(const Node& node) {
176 if (node.isElementNode()) { 187 if (node.isElementNode()) {
177 const Element& currentElement = toElement(node); 188 const Element& currentElement = toElement(node);
178 Node* first = currentElement.pseudoElement(PseudoIdBefore); 189 Node* first = currentElement.pseudoElement(PseudoIdBefore);
179 if (first) 190 if (first)
180 return first; 191 return first;
181 first = firstChild(currentElement); 192 first = LayoutTreeBuilderTraversal::firstChild(currentElement);
182 if (!first) 193 if (!first)
183 first = currentElement.pseudoElement(PseudoIdAfter); 194 first = currentElement.pseudoElement(PseudoIdAfter);
184 return first; 195 return first;
185 } 196 }
186 197
187 return firstChild(node); 198 return LayoutTreeBuilderTraversal::firstChild(node);
188 } 199 }
189 200
190 static Node* nextAncestorSibling(const Node& node, const Node* stayWithin) { 201 static Node* nextAncestorSibling(const Node& node, const Node* stayWithin) {
191 DCHECK(!pseudoAwareNextSibling(node)); 202 DCHECK(!pseudoAwareNextSibling(node));
192 DCHECK_NE(node, stayWithin); 203 DCHECK_NE(node, stayWithin);
193 for (Node* parentNode = parent(node); parentNode; 204 for (Node* parentNode = LayoutTreeBuilderTraversal::parent(node); parentNode;
194 parentNode = parent(*parentNode)) { 205 parentNode = LayoutTreeBuilderTraversal::parent(*parentNode)) {
195 if (parentNode == stayWithin) 206 if (parentNode == stayWithin)
196 return 0; 207 return 0;
197 if (Node* nextNode = pseudoAwareNextSibling(*parentNode)) 208 if (Node* nextNode = pseudoAwareNextSibling(*parentNode))
198 return nextNode; 209 return nextNode;
199 } 210 }
200 return 0; 211 return 0;
201 } 212 }
202 213
203 Node* nextSkippingChildren(const Node& node, const Node* stayWithin) { 214 Node* LayoutTreeBuilderTraversal::nextSkippingChildren(const Node& node,
215 const Node* stayWithin) {
204 if (node == stayWithin) 216 if (node == stayWithin)
205 return 0; 217 return 0;
206 if (Node* nextNode = pseudoAwareNextSibling(node)) 218 if (Node* nextNode = pseudoAwareNextSibling(node))
207 return nextNode; 219 return nextNode;
208 return nextAncestorSibling(node, stayWithin); 220 return nextAncestorSibling(node, stayWithin);
209 } 221 }
210 222
211 Node* next(const Node& node, const Node* stayWithin) { 223 Node* LayoutTreeBuilderTraversal::next(const Node& node,
224 const Node* stayWithin) {
212 if (Node* child = pseudoAwareFirstChild(node)) 225 if (Node* child = pseudoAwareFirstChild(node))
213 return child; 226 return child;
214 return nextSkippingChildren(node, stayWithin); 227 return nextSkippingChildren(node, stayWithin);
215 } 228 }
216 229
217 LayoutObject* nextSiblingLayoutObject(const Node& node, int32_t limit) { 230 static LayoutObject* nextSiblingLayoutObjectInternal(Node* node,
218 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; 231 int32_t& limit) {
219 for (Node* sibling = LayoutTreeBuilderTraversal::nextSibling(node); 232 for (Node* sibling = node; sibling && limit-- != 0;
220 sibling && limit-- != 0;
221 sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) { 233 sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) {
222 LayoutObject* layoutObject = sibling->layoutObject(); 234 LayoutObject* layoutObject = sibling->layoutObject();
235
236 #if DCHECK_IS_ON()
237 if (hasDisplayContentsStyle(*sibling))
238 DCHECK(!layoutObject);
239 #endif
240
241 if (!layoutObject && hasDisplayContentsStyle(*sibling)) {
242 layoutObject = nextSiblingLayoutObjectInternal(
243 pseudoAwareFirstChild(*sibling), limit);
244 if (layoutObject)
245 return layoutObject;
246 if (!limit)
247 return nullptr;
248 }
249
223 if (layoutObject && !isLayoutObjectReparented(layoutObject)) 250 if (layoutObject && !isLayoutObjectReparented(layoutObject))
224 return layoutObject; 251 return layoutObject;
225 } 252 }
226 return 0; 253
254 return nullptr;
227 } 255 }
228 256
229 LayoutObject* previousSiblingLayoutObject(const Node& node, int32_t limit) { 257 LayoutObject* LayoutTreeBuilderTraversal::nextSiblingLayoutObject(
258 const Node& node,
259 int32_t limit) {
230 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; 260 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit;
231 for (Node* sibling = LayoutTreeBuilderTraversal::previousSibling(node); 261 if (LayoutObject* sibling =
232 sibling && limit-- != 0; 262 nextSiblingLayoutObjectInternal(nextSibling(node), limit))
263 return sibling;
264
265 Node* parent = LayoutTreeBuilderTraversal::parent(node);
266 while (limit && parent && hasDisplayContentsStyle(*parent)) {
267 if (LayoutObject* sibling =
268 nextSiblingLayoutObjectInternal(nextSibling(*parent), limit))
269 return sibling;
270 parent = LayoutTreeBuilderTraversal::parent(*parent);
271 }
272
273 return nullptr;
274 }
275
276 static LayoutObject* previousSiblingLayoutObjectInternal(Node* node,
277 int32_t& limit) {
278 for (Node* sibling = node; sibling && limit-- != 0;
233 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) { 279 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) {
234 LayoutObject* layoutObject = sibling->layoutObject(); 280 LayoutObject* layoutObject = sibling->layoutObject();
281
282 #if DCHECK_IS_ON()
283 if (hasDisplayContentsStyle(*sibling))
284 DCHECK(!layoutObject);
285 #endif
286
287 if (!layoutObject && hasDisplayContentsStyle(*sibling)) {
288 layoutObject = previousSiblingLayoutObjectInternal(
289 pseudoAwareLastChild(*sibling), limit);
290 if (layoutObject)
291 return layoutObject;
292 if (!limit)
293 return nullptr;
294 }
295
235 if (layoutObject && !isLayoutObjectReparented(layoutObject)) 296 if (layoutObject && !isLayoutObjectReparented(layoutObject))
236 return layoutObject; 297 return layoutObject;
237 } 298 }
238 return 0; 299
300 return nullptr;
239 } 301 }
240 302
241 LayoutObject* nextInTopLayer(const Element& element) { 303 LayoutObject* LayoutTreeBuilderTraversal::previousSiblingLayoutObject(
304 const Node& node,
305 int32_t limit) {
306 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit;
307 if (LayoutObject* sibling =
308 previousSiblingLayoutObjectInternal(previousSibling(node), limit))
309 return sibling;
310
311 Node* parent = LayoutTreeBuilderTraversal::parent(node);
312 while (limit && parent && hasDisplayContentsStyle(*parent)) {
313 if (LayoutObject* sibling = previousSiblingLayoutObjectInternal(
314 previousSibling(*parent), limit))
315 return sibling;
316 parent = LayoutTreeBuilderTraversal::parent(*parent);
317 }
318
319 return nullptr;
320 }
321
322 LayoutObject* LayoutTreeBuilderTraversal::nextInTopLayer(
323 const Element& element) {
242 if (!element.isInTopLayer()) 324 if (!element.isInTopLayer())
243 return 0; 325 return 0;
244 const HeapVector<Member<Element>>& topLayerElements = 326 const HeapVector<Member<Element>>& topLayerElements =
245 element.document().topLayerElements(); 327 element.document().topLayerElements();
246 size_t position = topLayerElements.find(&element); 328 size_t position = topLayerElements.find(&element);
247 DCHECK_NE(position, kNotFound); 329 DCHECK_NE(position, kNotFound);
248 for (size_t i = position + 1; i < topLayerElements.size(); ++i) { 330 for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
249 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject()) 331 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject())
250 return layoutObject; 332 return layoutObject;
251 } 333 }
252 return 0; 334 return 0;
253 } 335 }
254 336
255 } // namespace LayoutTreeBuilderTraversal
256
257 } // namespace blink 337 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698