summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h
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