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 |
(...skipping 17 matching lines...) Expand all Loading... | |
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 namespace LayoutTreeBuilderTraversal { |
37 | 37 |
38 inline static bool hasDisplayContentsStyle(const Node& node) { | |
39 return node.isElementNode() && toElement(node).displayContentsStyle(); | |
40 } | |
41 | |
38 static bool isLayoutObjectReparented(const LayoutObject* layoutObject) { | 42 static bool isLayoutObjectReparented(const LayoutObject* layoutObject) { |
39 if (!layoutObject->node()->isElementNode()) | 43 if (!layoutObject->node()->isElementNode()) |
40 return false; | 44 return false; |
41 if (toElement(layoutObject->node())->isInTopLayer()) | 45 if (toElement(layoutObject->node())->isInTopLayer()) |
42 return true; | 46 return true; |
47 | |
48 // NB: We intentionally ignore display:contents children here, since we aim to | |
49 // find them in the traversal. | |
rune
2016/11/08 13:09:20
I think you can just remove this comment. The repa
emilio
2016/11/08 15:43:01
Oh, ok, I see, will do.
| |
50 | |
43 return false; | 51 return false; |
44 } | 52 } |
45 | 53 |
46 void ParentDetails::didTraverseInsertionPoint( | 54 void ParentDetails::didTraverseInsertionPoint( |
47 const InsertionPoint* insertionPoint) { | 55 const InsertionPoint* insertionPoint) { |
48 if (!m_insertionPoint) { | 56 if (!m_insertionPoint) { |
49 m_insertionPoint = insertionPoint; | 57 m_insertionPoint = insertionPoint; |
50 } | 58 } |
51 } | 59 } |
52 | 60 |
53 inline static void assertPseudoElementParent( | 61 inline static void assertPseudoElementParent( |
54 const PseudoElement& pseudoElement) { | 62 const PseudoElement& pseudoElement) { |
55 DCHECK(pseudoElement.parentNode()); | 63 DCHECK(pseudoElement.parentNode()); |
56 DCHECK(pseudoElement.parentNode()->canParticipateInFlatTree()); | 64 DCHECK(pseudoElement.parentNode()->canParticipateInFlatTree()); |
57 } | 65 } |
58 | 66 |
59 ContainerNode* parent(const Node& node, ParentDetails* details) { | 67 ContainerNode* parent(const Node& node, ParentDetails* details) { |
60 // TODO(hayato): Uncomment this once we can be sure | 68 // TODO(hayato): Uncomment this once we can be sure |
61 // LayoutTreeBuilderTraversal::parent() is used only for a node which is | 69 // LayoutTreeBuilderTraversal::parent() is used only for a node which is |
62 // connected. | 70 // connected. |
63 // DCHECK(node.isConnected()); | 71 // DCHECK(node.isConnected()); |
64 if (node.isPseudoElement()) { | 72 if (node.isPseudoElement()) { |
65 assertPseudoElementParent(toPseudoElement(node)); | 73 assertPseudoElementParent(toPseudoElement(node)); |
66 return node.parentNode(); | 74 return node.parentNode(); |
67 } | 75 } |
68 return FlatTreeTraversal::parent(node, details); | 76 return FlatTreeTraversal::parent(node, details); |
69 } | 77 } |
70 | 78 |
79 LayoutObject* parentLayoutObject(const Node& node) { | |
80 ContainerNode* parent = LayoutTreeBuilderTraversal::parent(node); | |
81 | |
82 while (parent && hasDisplayContentsStyle(*parent)) { | |
83 parent = LayoutTreeBuilderTraversal::parent(*parent); | |
84 } | |
85 | |
86 return parent ? parent->layoutObject() : nullptr; | |
87 } | |
88 | |
71 Node* nextSibling(const Node& node) { | 89 Node* nextSibling(const Node& node) { |
72 if (node.isBeforePseudoElement()) { | 90 if (node.isBeforePseudoElement()) { |
73 assertPseudoElementParent(toPseudoElement(node)); | 91 assertPseudoElementParent(toPseudoElement(node)); |
74 if (Node* next = FlatTreeTraversal::firstChild(*node.parentNode())) | 92 if (Node* next = FlatTreeTraversal::firstChild(*node.parentNode())) |
75 return next; | 93 return next; |
76 } else { | 94 } else { |
77 if (node.isAfterPseudoElement()) | 95 if (node.isAfterPseudoElement()) |
78 return nullptr; | 96 return nullptr; |
79 if (Node* next = FlatTreeTraversal::nextSibling(node)) | 97 if (Node* next = FlatTreeTraversal::nextSibling(node)) |
80 return next; | 98 return next; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 return nextNode; | 225 return nextNode; |
208 return nextAncestorSibling(node, stayWithin); | 226 return nextAncestorSibling(node, stayWithin); |
209 } | 227 } |
210 | 228 |
211 Node* next(const Node& node, const Node* stayWithin) { | 229 Node* next(const Node& node, const Node* stayWithin) { |
212 if (Node* child = pseudoAwareFirstChild(node)) | 230 if (Node* child = pseudoAwareFirstChild(node)) |
213 return child; | 231 return child; |
214 return nextSkippingChildren(node, stayWithin); | 232 return nextSkippingChildren(node, stayWithin); |
215 } | 233 } |
216 | 234 |
235 static LayoutObject* nextSiblingLayoutObjectInternal(Node* node, | |
236 int32_t& limit) { | |
237 for (Node* sibling = node; sibling && limit-- != 0; | |
238 sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) { | |
239 LayoutObject* layoutObject = sibling->layoutObject(); | |
240 | |
241 #if DCHECK_IS_ON() | |
242 if (hasDisplayContentsStyle(*sibling)) | |
243 DCHECK(!layoutObject); | |
244 #endif | |
245 | |
246 if (!layoutObject && hasDisplayContentsStyle(*sibling)) { | |
247 layoutObject = nextSiblingLayoutObjectInternal( | |
248 pseudoAwareFirstChild(*sibling), limit); | |
249 if (layoutObject) | |
250 return layoutObject; | |
251 if (!limit) | |
252 return nullptr; | |
253 } | |
254 | |
255 if (layoutObject && !isLayoutObjectReparented(layoutObject)) | |
256 return layoutObject; | |
257 } | |
258 | |
259 return nullptr; | |
260 } | |
261 | |
217 LayoutObject* nextSiblingLayoutObject(const Node& node, int32_t limit) { | 262 LayoutObject* nextSiblingLayoutObject(const Node& node, int32_t limit) { |
218 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; | 263 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; |
219 for (Node* sibling = LayoutTreeBuilderTraversal::nextSibling(node); | 264 if (LayoutObject* foundLayoutObject = nextSiblingLayoutObjectInternal( |
220 sibling && limit-- != 0; | 265 LayoutTreeBuilderTraversal::nextSibling(node), limit)) |
221 sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) { | 266 return foundLayoutObject; |
267 | |
268 Node* maybeDisplayContentsParent = LayoutTreeBuilderTraversal::parent(node); | |
269 while (limit && maybeDisplayContentsParent && | |
270 hasDisplayContentsStyle(*maybeDisplayContentsParent)) { | |
271 Node* displayContentsSibling = | |
272 LayoutTreeBuilderTraversal::nextSibling(*maybeDisplayContentsParent); | |
273 if (LayoutObject* siblingLayoutObject = | |
274 nextSiblingLayoutObjectInternal(displayContentsSibling, limit)) | |
275 return siblingLayoutObject; | |
276 maybeDisplayContentsParent = | |
277 LayoutTreeBuilderTraversal::parent(*maybeDisplayContentsParent); | |
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; | |
286 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) { | |
222 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 = nextSiblingLayoutObjectInternal( | |
296 pseudoAwareFirstChild(*sibling), limit); | |
297 if (layoutObject) | |
298 return layoutObject; | |
299 if (!limit) | |
300 return nullptr; | |
301 } | |
302 | |
223 if (layoutObject && !isLayoutObjectReparented(layoutObject)) | 303 if (layoutObject && !isLayoutObjectReparented(layoutObject)) |
224 return layoutObject; | 304 return layoutObject; |
225 } | 305 } |
226 return 0; | 306 |
307 return nullptr; | |
227 } | 308 } |
228 | 309 |
229 LayoutObject* previousSiblingLayoutObject(const Node& node, int32_t limit) { | 310 LayoutObject* previousSiblingLayoutObject(const Node& node, int32_t limit) { |
230 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; | 311 DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; |
231 for (Node* sibling = LayoutTreeBuilderTraversal::previousSibling(node); | 312 if (LayoutObject* foundLayoutObject = previousSiblingLayoutObjectInternal( |
232 sibling && limit-- != 0; | 313 LayoutTreeBuilderTraversal::previousSibling(node), limit)) |
233 sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) { | 314 return foundLayoutObject; |
234 LayoutObject* layoutObject = sibling->layoutObject(); | 315 |
235 if (layoutObject && !isLayoutObjectReparented(layoutObject)) | 316 Node* maybeDisplayContentsParent = LayoutTreeBuilderTraversal::parent(node); |
236 return layoutObject; | 317 while (limit && maybeDisplayContentsParent && |
318 hasDisplayContentsStyle(*maybeDisplayContentsParent)) { | |
319 Node* displayContentsSibling = LayoutTreeBuilderTraversal::previousSibling( | |
320 *maybeDisplayContentsParent); | |
321 if (LayoutObject* siblingLayoutObject = | |
322 previousSiblingLayoutObjectInternal(displayContentsSibling, limit)) | |
323 return siblingLayoutObject; | |
324 maybeDisplayContentsParent = | |
325 LayoutTreeBuilderTraversal::parent(*maybeDisplayContentsParent); | |
237 } | 326 } |
238 return 0; | 327 |
328 return nullptr; | |
239 } | 329 } |
240 | 330 |
241 LayoutObject* nextInTopLayer(const Element& element) { | 331 LayoutObject* nextInTopLayer(const Element& element) { |
242 if (!element.isInTopLayer()) | 332 if (!element.isInTopLayer()) |
243 return 0; | 333 return 0; |
244 const HeapVector<Member<Element>>& topLayerElements = | 334 const HeapVector<Member<Element>>& topLayerElements = |
245 element.document().topLayerElements(); | 335 element.document().topLayerElements(); |
246 size_t position = topLayerElements.find(&element); | 336 size_t position = topLayerElements.find(&element); |
247 DCHECK_NE(position, kNotFound); | 337 DCHECK_NE(position, kNotFound); |
248 for (size_t i = position + 1; i < topLayerElements.size(); ++i) { | 338 for (size_t i = position + 1; i < topLayerElements.size(); ++i) { |
249 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject()) | 339 if (LayoutObject* layoutObject = topLayerElements[i]->layoutObject()) |
250 return layoutObject; | 340 return layoutObject; |
251 } | 341 } |
252 return 0; | 342 return 0; |
253 } | 343 } |
254 | 344 |
255 } // namespace LayoutTreeBuilderTraversal | 345 } // namespace LayoutTreeBuilderTraversal |
256 | 346 |
257 } // namespace blink | 347 } // namespace blink |
OLD | NEW |