OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ng/ng_block_layout_algorithm.h" | 5 #include "core/layout/ng/ng_block_layout_algorithm.h" |
6 | 6 |
7 #include "core/layout/ng/ng_absolute_utils.h" | 7 #include "core/layout/ng/ng_absolute_utils.h" |
8 #include "core/layout/ng/ng_block_break_token.h" | 8 #include "core/layout/ng/ng_block_break_token.h" |
9 #include "core/layout/ng/ng_block_child_iterator.h" | 9 #include "core/layout/ng/ng_block_child_iterator.h" |
10 #include "core/layout/ng/ng_box_fragment.h" | 10 #include "core/layout/ng/ng_box_fragment.h" |
11 #include "core/layout/ng/ng_constraint_space.h" | 11 #include "core/layout/ng/ng_constraint_space.h" |
12 #include "core/layout/ng/ng_constraint_space_builder.h" | 12 #include "core/layout/ng/ng_constraint_space_builder.h" |
13 #include "core/layout/ng/ng_floats_utils.h" | 13 #include "core/layout/ng/ng_floats_utils.h" |
14 #include "core/layout/ng/ng_fragment.h" | 14 #include "core/layout/ng/ng_fragment.h" |
15 #include "core/layout/ng/ng_fragment_builder.h" | 15 #include "core/layout/ng/ng_fragment_builder.h" |
16 #include "core/layout/ng/ng_inline_node.h" | 16 #include "core/layout/ng/ng_inline_node.h" |
17 #include "core/layout/ng/ng_layout_opportunity_iterator.h" | 17 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
18 #include "core/layout/ng/ng_length_utils.h" | 18 #include "core/layout/ng/ng_length_utils.h" |
19 #include "core/layout/ng/ng_line_builder.h" | 19 #include "core/layout/ng/ng_line_builder.h" |
20 #include "core/layout/ng/ng_out_of_flow_layout_part.h" | 20 #include "core/layout/ng/ng_out_of_flow_layout_part.h" |
| 21 #include "core/layout/ng/ng_space_utils.h" |
21 #include "core/style/ComputedStyle.h" | 22 #include "core/style/ComputedStyle.h" |
22 #include "platform/LengthFunctions.h" | 23 #include "platform/LengthFunctions.h" |
23 #include "wtf/Optional.h" | 24 #include "wtf/Optional.h" |
24 | 25 |
25 namespace blink { | 26 namespace blink { |
26 namespace { | 27 namespace { |
27 | 28 |
28 // Whether child's constraint space should shrink to its intrinsic width. | 29 // Whether child's constraint space should shrink to its intrinsic width. |
29 // This is needed for buttons, select, input, floats and orthogonal children. | 30 // This is needed for buttons, select, input, floats and orthogonal children. |
30 // See LayoutBox::sizesLogicalWidthToFitContent for the rationale behind this. | 31 // See LayoutBox::sizesLogicalWidthToFitContent for the rationale behind this. |
31 bool ShouldShrinkToFit(const NGConstraintSpace& parent_space, | 32 bool ShouldShrinkToFit(const NGConstraintSpace& parent_space, |
32 const ComputedStyle& child_style) { | 33 const ComputedStyle& child_style) { |
33 NGWritingMode child_writing_mode = | 34 NGWritingMode child_writing_mode = |
34 FromPlatformWritingMode(child_style.getWritingMode()); | 35 FromPlatformWritingMode(child_style.getWritingMode()); |
35 // Whether the child and the containing block are parallel to each other. | 36 // Whether the child and the containing block are parallel to each other. |
36 // Example: vertical-rl and vertical-lr | 37 // Example: vertical-rl and vertical-lr |
37 bool is_in_parallel_flow = | 38 bool is_in_parallel_flow = |
38 IsParallelWritingMode(parent_space.WritingMode(), child_writing_mode); | 39 IsParallelWritingMode(parent_space.WritingMode(), child_writing_mode); |
39 | 40 |
40 return child_style.display() == EDisplay::kInlineBlock || | 41 return child_style.display() == EDisplay::kInlineBlock || |
41 child_style.isFloating() || !is_in_parallel_flow; | 42 child_style.isFloating() || !is_in_parallel_flow; |
42 } | 43 } |
43 | 44 |
44 // Returns max of 2 {@code WTF::Optional} values. | |
45 template <typename T> | |
46 WTF::Optional<T> OptionalMax(const WTF::Optional<T>& value1, | |
47 const WTF::Optional<T>& value2) { | |
48 if (value1 && value2) { | |
49 return std::max(value1.value(), value2.value()); | |
50 } else if (value1) { | |
51 return value1; | |
52 } | |
53 return value2; | |
54 } | |
55 | |
56 WTF::Optional<LayoutUnit> GetClearanceOffset( | |
57 const std::shared_ptr<NGExclusions>& exclusions, | |
58 const ComputedStyle& style) { | |
59 const NGExclusion* right_exclusion = exclusions->last_right_float; | |
60 const NGExclusion* left_exclusion = exclusions->last_left_float; | |
61 | |
62 WTF::Optional<LayoutUnit> left_offset; | |
63 if (left_exclusion) { | |
64 left_offset = left_exclusion->rect.BlockEndOffset(); | |
65 } | |
66 WTF::Optional<LayoutUnit> right_offset; | |
67 if (right_exclusion) { | |
68 right_offset = right_exclusion->rect.BlockEndOffset(); | |
69 } | |
70 | |
71 switch (style.clear()) { | |
72 case EClear::kNone: | |
73 return WTF::nullopt; // nothing to do here. | |
74 case EClear::kLeft: | |
75 return left_offset; | |
76 case EClear::kRight: | |
77 return right_offset; | |
78 case EClear::kBoth: | |
79 return OptionalMax<LayoutUnit>(left_offset, right_offset); | |
80 default: | |
81 ASSERT_NOT_REACHED(); | |
82 } | |
83 return WTF::nullopt; | |
84 } | |
85 | |
86 // Positions pending floats stored on the fragment builder starting from | 45 // Positions pending floats stored on the fragment builder starting from |
87 // {@code origin_point_block_offset}. | 46 // {@code origin_point_block_offset}. |
88 void PositionPendingFloats(const LayoutUnit origin_point_block_offset, | 47 void PositionPendingFloats(const LayoutUnit origin_point_block_offset, |
89 NGConstraintSpace* new_parent_space, | 48 NGConstraintSpace* new_parent_space, |
90 NGFragmentBuilder* builder) { | 49 NGFragmentBuilder* builder) { |
91 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; | 50 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; |
92 LayoutUnit bfc_block_offset = builder->BfcOffset().value().block_offset; | 51 LayoutUnit bfc_block_offset = builder->BfcOffset().value().block_offset; |
93 | 52 |
94 for (auto& floating_object : builder->UnpositionedFloats()) { | 53 for (auto& floating_object : builder->UnpositionedFloats()) { |
95 const auto* float_space = floating_object->space.get(); | 54 const auto* float_space = floating_object->space.get(); |
96 const NGConstraintSpace* original_parent_space = | 55 const NGConstraintSpace* original_parent_space = |
97 floating_object->original_parent_space.get(); | 56 floating_object->original_parent_space.get(); |
98 | 57 |
99 NGLogicalOffset origin_point = {float_space->BfcOffset().inline_offset, | 58 NGLogicalOffset origin_point = {float_space->BfcOffset().inline_offset, |
100 origin_point_block_offset}; | 59 origin_point_block_offset}; |
101 NGLogicalOffset from_offset = { | 60 NGLogicalOffset from_offset = { |
102 original_parent_space->BfcOffset().inline_offset, bfc_block_offset}; | 61 original_parent_space->BfcOffset().inline_offset, bfc_block_offset}; |
103 | 62 |
104 NGLogicalOffset float_fragment_offset = PositionFloat( | 63 NGLogicalOffset float_fragment_offset = PositionFloat( |
105 origin_point, from_offset, floating_object.get(), new_parent_space); | 64 origin_point, from_offset, floating_object.get(), new_parent_space); |
106 builder->AddFloatingObject(floating_object, float_fragment_offset); | 65 builder->AddFloatingObject(floating_object, float_fragment_offset); |
107 } | 66 } |
108 builder->MutableUnpositionedFloats().clear(); | 67 builder->MutableUnpositionedFloats().clear(); |
109 } | 68 } |
110 | 69 |
111 // Whether an in-flow block-level child creates a new formatting context. | |
112 // | |
113 // This will *NOT* check the following cases: | |
114 // - The child is out-of-flow, e.g. floating or abs-pos. | |
115 // - The child is a inline-level, e.g. "display: inline-block". | |
116 // - The child establishes a new formatting context, but should be a child of | |
117 // another layout algorithm, e.g. "display: table-caption" or flex-item. | |
118 bool IsNewFormattingContextForInFlowBlockLevelChild( | |
119 const NGConstraintSpace& space, | |
120 const ComputedStyle& style) { | |
121 // TODO(layout-dev): This doesn't capture a few cases which can't be computed | |
122 // directly from style yet: | |
123 // - The child is a <fieldset>. | |
124 // - "column-span: all" is set on the child (requires knowledge that we are | |
125 // in a multi-col formatting context). | |
126 // (https://drafts.csswg.org/css-multicol-1/#valdef-column-span-all) | |
127 | |
128 if (style.specifiesColumns() || style.containsPaint() || | |
129 style.containsLayout()) | |
130 return true; | |
131 | |
132 if (!style.isOverflowVisible()) | |
133 return true; | |
134 | |
135 EDisplay display = style.display(); | |
136 if (display == EDisplay::kGrid || display == EDisplay::kFlex || | |
137 display == EDisplay::kWebkitBox) | |
138 return true; | |
139 | |
140 if (space.WritingMode() != FromPlatformWritingMode(style.getWritingMode())) | |
141 return true; | |
142 | |
143 return false; | |
144 } | |
145 | |
146 // Whether we've run out of space in this flow. If so, there will be no work | 70 // Whether we've run out of space in this flow. If so, there will be no work |
147 // left to do for this block in this fragmentainer. | 71 // left to do for this block in this fragmentainer. |
148 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) { | 72 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) { |
149 return space.HasBlockFragmentation() && | 73 return space.HasBlockFragmentation() && |
150 content_size >= space.FragmentainerSpaceAvailable(); | 74 content_size >= space.FragmentainerSpaceAvailable(); |
151 } | 75 } |
152 | 76 |
153 } // namespace | 77 } // namespace |
154 | 78 |
155 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( | 79 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 DCHECK(builder_.BfcOffset()); | 527 DCHECK(builder_.BfcOffset()); |
604 space_available -= curr_bfc_offset_.block_offset; | 528 space_available -= curr_bfc_offset_.block_offset; |
605 } | 529 } |
606 } | 530 } |
607 space_builder_.SetFragmentainerSpaceAvailable(space_available); | 531 space_builder_.SetFragmentainerSpaceAvailable(space_available); |
608 | 532 |
609 return space_builder_.ToConstraintSpace( | 533 return space_builder_.ToConstraintSpace( |
610 FromPlatformWritingMode(child_style.getWritingMode())); | 534 FromPlatformWritingMode(child_style.getWritingMode())); |
611 } | 535 } |
612 } // namespace blink | 536 } // namespace blink |
OLD | NEW |