1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/core/layout/ng/layout_box_utils.h"
6
7 #include "third_party/blink/renderer/core/layout/layout_block.h"
8 #include "third_party/blink/renderer/core/layout/layout_box.h"
9 #include "third_party/blink/renderer/core/layout/layout_view.h"
10 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
11 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h"
12 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
13 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
14 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
15 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
16
17 namespace blink {
18
AvailableLogicalWidth(const LayoutBox & box,const LayoutBlock * cb)19 LayoutUnit LayoutBoxUtils::AvailableLogicalWidth(const LayoutBox& box,
20 const LayoutBlock* cb) {
21 auto writing_mode = box.StyleRef().GetWritingMode();
22 bool parallel_containing_block = IsParallelWritingMode(
23 cb ? cb->StyleRef().GetWritingMode() : writing_mode, writing_mode);
24
25 // Grid layout sets OverrideContainingBlockContentLogicalWidth|Height
26 if (parallel_containing_block &&
27 box.HasOverrideContainingBlockContentLogicalWidth()) {
28 return box.OverrideContainingBlockContentLogicalWidth()
29 .ClampNegativeToZero();
30 }
31
32 if (!parallel_containing_block &&
33 box.HasOverrideContainingBlockContentLogicalHeight()) {
34 return box.OverrideContainingBlockContentLogicalHeight()
35 .ClampNegativeToZero();
36 }
37
38 if (parallel_containing_block)
39 return box.ContainingBlockLogicalWidthForContent().ClampNegativeToZero();
40
41 return box.PerpendicularContainingBlockLogicalHeight().ClampNegativeToZero();
42 }
43
AvailableLogicalHeight(const LayoutBox & box,const LayoutBlock * cb)44 LayoutUnit LayoutBoxUtils::AvailableLogicalHeight(const LayoutBox& box,
45 const LayoutBlock* cb) {
46 auto writing_mode = box.StyleRef().GetWritingMode();
47 bool parallel_containing_block = IsParallelWritingMode(
48 cb ? cb->StyleRef().GetWritingMode() : writing_mode, writing_mode);
49
50 // Grid layout sets OverrideContainingBlockContentLogicalWidth|Height
51 if (parallel_containing_block &&
52 box.HasOverrideContainingBlockContentLogicalHeight())
53 return box.OverrideContainingBlockContentLogicalHeight();
54
55 if (!parallel_containing_block &&
56 box.HasOverrideContainingBlockContentLogicalWidth())
57 return box.OverrideContainingBlockContentLogicalWidth();
58
59 if (!box.Parent())
60 return box.View()->ViewLogicalHeightForPercentages();
61
62 DCHECK(cb);
63 if (parallel_containing_block)
64 return box.ContainingBlockLogicalHeightForPercentageResolution();
65
66 return box.ContainingBlockLogicalWidthForContent();
67 }
68
ComputeStaticPositionFromLegacy(const LayoutBox & box,const NGBoxStrut & container_border_scrollbar,const NGBoxFragmentBuilder * container_builder)69 NGLogicalStaticPosition LayoutBoxUtils::ComputeStaticPositionFromLegacy(
70 const LayoutBox& box,
71 const NGBoxStrut& container_border_scrollbar,
72 const NGBoxFragmentBuilder* container_builder) {
73 const LayoutBoxModelObject* css_container =
74 ToLayoutBoxModelObject(box.Container());
75 const TextDirection parent_direction = box.Parent()->StyleRef().Direction();
76
77 // These two values represent the available-size for the OOF-positioned
78 // descandant, in the *descendant's* writing mode.
79 LayoutUnit containing_block_logical_width =
80 box.ContainingBlockLogicalWidthForPositioned(css_container);
81 LayoutUnit containing_block_logical_height =
82 box.ContainingBlockLogicalHeightForPositioned(css_container);
83
84 Length logical_left;
85 Length logical_right;
86 Length logical_top;
87 Length logical_bottom;
88 box.ComputeInlineStaticDistance(logical_left, logical_right, &box,
89 css_container, containing_block_logical_width,
90 container_builder);
91 box.ComputeBlockStaticDistance(logical_top, logical_bottom, &box,
92 css_container, container_builder);
93
94 // Determine the static-position.
95 LayoutUnit static_line;
96 LayoutUnit static_block;
97 if (IsLtr(parent_direction)) {
98 if (!logical_left.IsAuto()) {
99 static_line =
100 MinimumValueForLength(logical_left, containing_block_logical_width);
101 }
102 } else {
103 if (!logical_right.IsAuto()) {
104 static_line =
105 MinimumValueForLength(logical_right, containing_block_logical_width);
106 }
107
108 // |logical_right| is an adjustment from the right edge, to keep this
109 // relative to the line-left edge account for the
110 // |containing_block_logical_width|.
111 static_line = containing_block_logical_width - static_line;
112 }
113 if (!logical_top.IsAuto()) {
114 static_block =
115 MinimumValueForLength(logical_top, containing_block_logical_height);
116 }
117
118 NGLogicalStaticPosition logical_static_position{
119 {static_line, static_block},
120 IsLtr(parent_direction)
121 ? NGLogicalStaticPosition::InlineEdge::kInlineStart
122 : NGLogicalStaticPosition::InlineEdge::kInlineEnd,
123 NGLogicalStaticPosition::BlockEdge::kBlockStart};
124
125 // Determine the physical available-size, remember that the available-size is
126 // currently in the *descendant's* writing-mode.
127 PhysicalSize container_size =
128 ToPhysicalSize(LogicalSize(containing_block_logical_width,
129 containing_block_logical_height),
130 box.StyleRef().GetWritingMode());
131
132 const LayoutBox* container = css_container->IsBox()
133 ? ToLayoutBox(css_container)
134 : box.ContainingBlock();
135 const WritingMode container_writing_mode =
136 container->StyleRef().GetWritingMode();
137 const TextDirection container_direction = container->StyleRef().Direction();
138
139 // We perform a logical-physical-logical conversion to convert the
140 // static-position into the correct writing-mode, and direction combination.
141 //
142 // At the moment the static-position is in line-relative coordinates which is
143 // why we use |TextDirection::kLtr| for the first conversion.
144 logical_static_position =
145 logical_static_position
146 .ConvertToPhysical(container_writing_mode, TextDirection::kLtr,
147 container_size)
148 .ConvertToLogical(container_writing_mode, container_direction,
149 container_size);
150
151 // Finally we shift the static-position from being relative to the
152 // padding-box, to the border-box.
153 logical_static_position.offset +=
154 LogicalOffset{container_border_scrollbar.inline_start,
155 container_border_scrollbar.block_start};
156 return logical_static_position;
157 }
158
SkipContainingBlockForPercentHeightCalculation(const LayoutBlock * cb)159 bool LayoutBoxUtils::SkipContainingBlockForPercentHeightCalculation(
160 const LayoutBlock* cb) {
161 return LayoutBox::SkipContainingBlockForPercentHeightCalculation(cb);
162 }
163
164 } // namespace blink
165