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