blob: 7d8327a837509f8a5bb2e379691d01ad81dbb022 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LegacyLayoutTreeWalking_h
#define LegacyLayoutTreeWalking_h
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
// We still have the legacy layout tree structure, which means that a multicol
// container LayoutBlockFlow will consist of a LayoutFlowThread child, followed
// by zero or more siblings of type LayoutMultiColumnSet and/or
// LayoutMultiColumnSpannerPlaceholder. NG needs to skip these special
// objects. The actual content is inside the flow thread. There are similar
// complications for fieldset / legend.
namespace blink {
// Return the layout object that should be the first child NGLayoutInputNode of
// |parent|. Normally this will just be the first layout object child, but there
// are certain layout objects that should be skipped for NG.
inline LayoutObject* GetLayoutObjectForFirstChildNode(LayoutBlock* parent) {
LayoutObject* child = parent->FirstChild();
if (!child)
return nullptr;
if (UNLIKELY(child->IsLayoutFlowThread()))
return To<LayoutBlockFlow>(child)->FirstChild();
// The rendered legend is a child of the anonymous wrapper inside the fieldset
// container. If we find it, skip it. As far as NG is concerned, the rendered
// legend is a child of the fieldset container.
if (UNLIKELY(child->IsRenderedLegend()))
return child->NextSibling();
return child;
}
// Return the layout object that should be the parent NGLayoutInputNode of
// |object|. Normally this will just be the parent layout object, but there
// are certain layout objects that should be skipped for NG.
inline LayoutObject* GetLayoutObjectForParentNode(LayoutObject* object) {
// First check that we're not walking where we shouldn't be walking.
DCHECK(!object->IsLayoutFlowThread());
DCHECK(!object->IsLayoutMultiColumnSet());
DCHECK(!object->IsLayoutMultiColumnSpannerPlaceholder());
LayoutObject* parent = object->Parent();
if (UNLIKELY(!parent))
return nullptr;
// The parent of the rendered legend is the fieldset container, as far as NG
// is concerned. Skip the anonymous wrapper in-between.
if (UNLIKELY(object->IsRenderedLegend()))
return parent->Parent();
if (UNLIKELY(parent->IsLayoutFlowThread()))
return parent->Parent();
return parent;
}
// Return the layout object that should be the sibling NGLayoutInputNode of
// |object|. Normally this will just be the next sibling layout object, but
// there are certain layout objects that should be skipped for NG.
inline LayoutObject* GetLayoutObjectForNextSiblingNode(LayoutObject* object) {
// We don't expect to walk the layout tree starting at the rendered legend,
// and we'll skip over it if we find it. The renderered legend will be handled
// by a special algorithm, and should be invisible among siblings.
DCHECK(!object->IsRenderedLegend());
LayoutObject* next = object->NextSibling();
if (!next)
return nullptr;
if (UNLIKELY(next->IsRenderedLegend()))
return next->NextSibling();
return next;
}
// Return true if the NGLayoutInputNode children of the NGLayoutInputNode
// established by |block| will be inline; see LayoutObject::ChildrenInline().
inline bool AreNGBlockFlowChildrenInline(const LayoutBlock* block) {
if (block->ChildrenInline())
return true;
if (const auto* first_child = block->FirstChild()) {
if (UNLIKELY(first_child->IsLayoutFlowThread()))
return first_child->ChildrenInline();
}
return false;
}
// Return true if the block is of NG type, or if it's a block invisible to
// LayoutNG and it has an NG containg block. False if it's hosted by the legacy
// layout engine.
inline bool IsLayoutNGContainingBlock(const LayoutBlock* containing_block) {
if (UNLIKELY(containing_block->IsLayoutFlowThread()))
containing_block = containing_block->ContainingBlock();
return containing_block && (containing_block->IsLayoutNGMixin() ||
containing_block->IsLayoutNGFlexibleBox());
}
// Return true if the layout object is a LayoutNG object that is managed by the
// LayoutNG engine (i.e. its containing block is a LayoutNG object as well).
inline bool IsManagedByLayoutNG(const LayoutObject& object) {
if (!object.IsLayoutNGMixin() && !object.IsLayoutNGFlexibleBox())
return false;
const auto* containing_block = object.ContainingBlock();
if (UNLIKELY(!containing_block))
return false;
return IsLayoutNGContainingBlock(containing_block);
}
} // namespace blink
#endif // LegacyLayoutTreeWalking_h
|