OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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_floats_utils.h" | 5 #include "core/layout/ng/ng_floats_utils.h" |
6 | 6 |
7 #include "core/layout/ng/ng_box_fragment.h" | 7 #include "core/layout/ng/ng_box_fragment.h" |
| 8 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
8 | 9 |
9 namespace blink { | 10 namespace blink { |
10 namespace { | 11 namespace { |
11 | 12 |
12 // Adjusts the provided offset to the top edge alignment rule. | 13 // Adjusts the provided offset to the top edge alignment rule. |
13 // Top edge alignment rule: the outer top of a floating box may not be higher | 14 // Top edge alignment rule: the outer top of a floating box may not be higher |
14 // than the outer top of any block or floated box generated by an element | 15 // than the outer top of any block or floated box generated by an element |
15 // earlier in the source document. | 16 // earlier in the source document. |
16 NGLogicalOffset AdjustToTopEdgeAlignmentRule(const NGConstraintSpace& space, | 17 NGLogicalOffset AdjustToTopEdgeAlignmentRule(const NGConstraintSpace& space, |
17 const NGLogicalOffset& offset) { | 18 const NGLogicalOffset& offset) { |
18 NGLogicalOffset adjusted_offset = offset; | 19 NGLogicalOffset adjusted_offset = offset; |
19 LayoutUnit& adjusted_block_offset = adjusted_offset.block_offset; | 20 LayoutUnit& adjusted_block_offset = adjusted_offset.block_offset; |
20 if (space.Exclusions()->last_left_float) | 21 if (space.Exclusions()->last_left_float) |
21 adjusted_block_offset = | 22 adjusted_block_offset = |
22 std::max(adjusted_block_offset, | 23 std::max(adjusted_block_offset, |
23 space.Exclusions()->last_left_float->rect.BlockStartOffset()); | 24 space.Exclusions()->last_left_float->rect.BlockStartOffset()); |
24 if (space.Exclusions()->last_right_float) | 25 if (space.Exclusions()->last_right_float) |
25 adjusted_block_offset = | 26 adjusted_block_offset = |
26 std::max(adjusted_block_offset, | 27 std::max(adjusted_block_offset, |
27 space.Exclusions()->last_right_float->rect.BlockStartOffset()); | 28 space.Exclusions()->last_right_float->rect.BlockStartOffset()); |
28 return adjusted_offset; | 29 return adjusted_offset; |
29 } | 30 } |
30 | 31 |
31 // Finds a layout opportunity for the fragment. | 32 NGLayoutOpportunity FindLayoutOpportunityForFloat( |
32 // It iterates over all layout opportunities in the constraint space and returns | |
33 // the first layout opportunity that is wider than the fragment or returns the | |
34 // last one which is always the widest. | |
35 // | |
36 // @param space Constraint space that is used to find layout opportunity for | |
37 // the fragment. | |
38 // @param fragment Fragment that needs to be placed. | |
39 // @param floating_object Floating object for which we need to find a layout | |
40 // opportunity. | |
41 // @return Layout opportunity for the fragment. | |
42 const NGLayoutOpportunity FindLayoutOpportunityForFragment( | |
43 const NGConstraintSpace* space, | 33 const NGConstraintSpace* space, |
44 const NGFragment& fragment, | 34 const NGFragment& fragment, |
45 const NGFloatingObject* floating_object) { | 35 const NGFloatingObject* floating_object) { |
46 NGLogicalOffset adjusted_origin_point = | 36 NGLogicalOffset adjusted_origin_point = |
47 AdjustToTopEdgeAlignmentRule(*space, floating_object->origin_offset); | 37 AdjustToTopEdgeAlignmentRule(*space, floating_object->origin_offset); |
48 | 38 return FindLayoutOpportunityForFragment( |
49 NGLayoutOpportunityIterator opportunity_iter(space->Exclusions().get(), | 39 space->Exclusions().get(), floating_object->available_size, |
50 floating_object->available_size, | 40 adjusted_origin_point, floating_object->margins, fragment); |
51 adjusted_origin_point); | |
52 NGLayoutOpportunity opportunity; | |
53 NGLayoutOpportunity opportunity_candidate = opportunity_iter.Next(); | |
54 | |
55 NGBoxStrut margins = floating_object->margins; | |
56 while (!opportunity_candidate.IsEmpty()) { | |
57 opportunity = opportunity_candidate; | |
58 // Checking opportunity's block size is not necessary as a float cannot be | |
59 // positioned on top of another float inside of the same constraint space. | |
60 auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum(); | |
61 if (opportunity.size.inline_size >= fragment_inline_size) | |
62 break; | |
63 | |
64 opportunity_candidate = opportunity_iter.Next(); | |
65 } | |
66 return opportunity; | |
67 } | 41 } |
68 | 42 |
69 // Calculates the logical offset for opportunity. | 43 // Calculates the logical offset for opportunity. |
70 NGLogicalOffset CalculateLogicalOffsetForOpportunity( | 44 NGLogicalOffset CalculateLogicalOffsetForOpportunity( |
71 const NGLayoutOpportunity& opportunity, | 45 const NGLayoutOpportunity& opportunity, |
72 const LayoutUnit float_offset, | 46 const LayoutUnit float_offset, |
73 const NGFloatingObject* floating_object) { | 47 const NGFloatingObject* floating_object) { |
74 DCHECK(floating_object); | 48 DCHECK(floating_object); |
75 auto margins = floating_object->margins; | 49 auto margins = floating_object->margins; |
76 // Adjust to child's margin. | 50 // Adjust to child's margin. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 NGConstraintSpace* new_parent_space) { | 95 NGConstraintSpace* new_parent_space) { |
122 DCHECK(floating_object); | 96 DCHECK(floating_object); |
123 DCHECK(floating_object->fragment) << "Fragment cannot be null here"; | 97 DCHECK(floating_object->fragment) << "Fragment cannot be null here"; |
124 | 98 |
125 // TODO(ikilpatrick): The writing mode switching here looks wrong. | 99 // TODO(ikilpatrick): The writing mode switching here looks wrong. |
126 NGBoxFragment float_fragment( | 100 NGBoxFragment float_fragment( |
127 floating_object->writing_mode, | 101 floating_object->writing_mode, |
128 ToNGPhysicalBoxFragment(floating_object->fragment.Get())); | 102 ToNGPhysicalBoxFragment(floating_object->fragment.Get())); |
129 | 103 |
130 // Find a layout opportunity that will fit our float. | 104 // Find a layout opportunity that will fit our float. |
131 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( | 105 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFloat( |
132 new_parent_space, float_fragment, floating_object); | 106 new_parent_space, float_fragment, floating_object); |
133 | 107 |
134 // TODO(glebl): This should check for infinite opportunity instead. | 108 // TODO(glebl): This should check for infinite opportunity instead. |
135 if (opportunity.IsEmpty()) { | 109 if (opportunity.IsEmpty()) { |
136 // Because of the implementation specific of the layout opportunity iterator | 110 // Because of the implementation specific of the layout opportunity iterator |
137 // an empty opportunity can mean 2 things: | 111 // an empty opportunity can mean 2 things: |
138 // - search for layout opportunities is exhausted. | 112 // - search for layout opportunities is exhausted. |
139 // - opportunity has an infinite size. That's because CS is infinite. | 113 // - opportunity has an infinite size. That's because CS is infinite. |
140 opportunity = NGLayoutOpportunity( | 114 opportunity = NGLayoutOpportunity( |
141 NGLogicalOffset(), | 115 NGLogicalOffset(), |
(...skipping 14 matching lines...) Expand all Loading... |
156 floating_object->exclusion_type); | 130 floating_object->exclusion_type); |
157 new_parent_space->AddExclusion(exclusion); | 131 new_parent_space->AddExclusion(exclusion); |
158 | 132 |
159 NGLogicalOffset logical_offset = CalculateLogicalOffsetForOpportunity( | 133 NGLogicalOffset logical_offset = CalculateLogicalOffsetForOpportunity( |
160 opportunity, float_offset, floating_object); | 134 opportunity, float_offset, floating_object); |
161 UpdateFloatingObjectLeftOffset(*new_parent_space, logical_offset, | 135 UpdateFloatingObjectLeftOffset(*new_parent_space, logical_offset, |
162 floating_object); | 136 floating_object); |
163 return logical_offset; | 137 return logical_offset; |
164 } | 138 } |
165 | 139 |
166 void PositionPendingFloats(const LayoutUnit& origin_block_offset, | 140 void PositionFloats(LayoutUnit origin_block_offset, |
167 NGConstraintSpace* space, | 141 LayoutUnit from_block_offset, |
168 NGFragmentBuilder* builder) { | 142 const Vector<RefPtr<NGFloatingObject>>& floating_objects, |
169 DCHECK(builder) << "Builder cannot be null here"; | 143 NGConstraintSpace* space) { |
170 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; | 144 for (auto& floating_object : floating_objects) { |
171 LayoutUnit bfc_block_offset = builder->BfcOffset().value().block_offset; | |
172 | |
173 for (auto& floating_object : builder->UnpositionedFloats()) { | |
174 floating_object->origin_offset.block_offset = origin_block_offset; | 145 floating_object->origin_offset.block_offset = origin_block_offset; |
175 floating_object->from_offset.block_offset = bfc_block_offset; | 146 floating_object->from_offset.block_offset = from_block_offset; |
176 | 147 floating_object->logical_offset = |
177 NGLogicalOffset offset = PositionFloat(floating_object.Get(), space); | 148 PositionFloat(floating_object.Get(), space); |
178 builder->AddFloatingObject(floating_object, offset); | |
179 } | 149 } |
180 builder->MutableUnpositionedFloats().clear(); | |
181 } | 150 } |
182 | 151 |
183 } // namespace blink | 152 } // namespace blink |
OLD | NEW |