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 | 8 |
9 namespace blink { | 9 namespace blink { |
10 namespace { | 10 namespace { |
(...skipping 18 matching lines...) Expand all Loading... |
29 } | 29 } |
30 | 30 |
31 // Finds a layout opportunity for the fragment. | 31 // Finds a layout opportunity for the fragment. |
32 // It iterates over all layout opportunities in the constraint space and returns | 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 | 33 // the first layout opportunity that is wider than the fragment or returns the |
34 // last one which is always the widest. | 34 // last one which is always the widest. |
35 // | 35 // |
36 // @param space Constraint space that is used to find layout opportunity for | 36 // @param space Constraint space that is used to find layout opportunity for |
37 // the fragment. | 37 // the fragment. |
38 // @param fragment Fragment that needs to be placed. | 38 // @param fragment Fragment that needs to be placed. |
39 // @param origin_point {@code space}'s offset relative to the space that | 39 // @param floating_object Floating object for which we need to find a layout |
40 // establishes a new formatting context that we're currently | 40 // opportunity. |
41 // in and where all our exclusions reside. | |
42 // @param margins Margins of the fragment. | |
43 // @param available_size Available size used by the layout opportunity iterator. | |
44 // @return Layout opportunity for the fragment. | 41 // @return Layout opportunity for the fragment. |
45 const NGLayoutOpportunity FindLayoutOpportunityForFragment( | 42 const NGLayoutOpportunity FindLayoutOpportunityForFragment( |
46 const NGConstraintSpace* space, | 43 const NGConstraintSpace* space, |
47 const NGFragment& fragment, | 44 const NGFragment& fragment, |
48 const NGLogicalOffset& origin_point, | 45 const NGFloatingObject* floating_object) { |
49 const NGBoxStrut& margins, | |
50 const NGLogicalSize& available_size) { | |
51 NGLogicalOffset adjusted_origin_point = | 46 NGLogicalOffset adjusted_origin_point = |
52 AdjustToTopEdgeAlignmentRule(*space, origin_point); | 47 AdjustToTopEdgeAlignmentRule(*space, floating_object->origin_offset); |
53 | 48 |
54 NGLayoutOpportunityIterator opportunity_iter(space, available_size, | 49 NGLayoutOpportunityIterator opportunity_iter( |
55 adjusted_origin_point); | 50 space, floating_object->available_size, adjusted_origin_point); |
56 NGLayoutOpportunity opportunity; | 51 NGLayoutOpportunity opportunity; |
57 NGLayoutOpportunity opportunity_candidate = opportunity_iter.Next(); | 52 NGLayoutOpportunity opportunity_candidate = opportunity_iter.Next(); |
58 | 53 |
| 54 NGBoxStrut margins = floating_object->margins; |
59 while (!opportunity_candidate.IsEmpty()) { | 55 while (!opportunity_candidate.IsEmpty()) { |
60 opportunity = opportunity_candidate; | 56 opportunity = opportunity_candidate; |
61 // Checking opportunity's block size is not necessary as a float cannot be | 57 // Checking opportunity's block size is not necessary as a float cannot be |
62 // positioned on top of another float inside of the same constraint space. | 58 // positioned on top of another float inside of the same constraint space. |
63 auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum(); | 59 auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum(); |
64 if (opportunity.size.inline_size >= fragment_inline_size) | 60 if (opportunity.size.inline_size >= fragment_inline_size) |
65 break; | 61 break; |
66 | 62 |
67 opportunity_candidate = opportunity_iter.Next(); | 63 opportunity_candidate = opportunity_iter.Next(); |
68 } | 64 } |
69 return opportunity; | 65 return opportunity; |
70 } | 66 } |
71 | 67 |
72 // Calculates the logical offset for opportunity. | 68 // Calculates the logical offset for opportunity. |
73 NGLogicalOffset CalculateLogicalOffsetForOpportunity( | 69 NGLogicalOffset CalculateLogicalOffsetForOpportunity( |
74 const NGLayoutOpportunity& opportunity, | 70 const NGLayoutOpportunity& opportunity, |
75 const LayoutUnit float_offset, | 71 const LayoutUnit float_offset, |
76 const NGLogicalOffset& from_offset, | 72 const NGFloatingObject* floating_object) { |
77 NGFloatingObject* floating_object) { | |
78 DCHECK(floating_object); | 73 DCHECK(floating_object); |
79 auto margins = floating_object->margins; | 74 auto margins = floating_object->margins; |
80 // Adjust to child's margin. | 75 // Adjust to child's margin. |
81 LayoutUnit inline_offset = margins.inline_start; | 76 NGLogicalOffset result = margins.InlineBlockStartOffset(); |
82 LayoutUnit block_offset = margins.block_start; | |
83 | 77 |
84 // Offset from the opportunity's block/inline start. | 78 // Offset from the opportunity's block/inline start. |
85 inline_offset += opportunity.offset.inline_offset; | 79 result += opportunity.offset; |
86 block_offset += opportunity.offset.block_offset; | |
87 | 80 |
88 // Adjust to float: right offset if needed. | 81 // Adjust to float: right offset if needed. |
89 inline_offset += float_offset; | 82 result.inline_offset += float_offset; |
90 | 83 |
91 block_offset -= from_offset.block_offset; | 84 result -= floating_object->from_offset; |
92 inline_offset -= from_offset.inline_offset; | 85 return result; |
93 | |
94 return NGLogicalOffset(inline_offset, block_offset); | |
95 } | 86 } |
96 | 87 |
97 // Creates an exclusion from the fragment that will be placed in the provided | 88 // Creates an exclusion from the fragment that will be placed in the provided |
98 // layout opportunity. | 89 // layout opportunity. |
99 NGExclusion CreateExclusion(const NGFragment& fragment, | 90 NGExclusion CreateExclusion(const NGFragment& fragment, |
100 const NGLayoutOpportunity& opportunity, | 91 const NGLayoutOpportunity& opportunity, |
101 const LayoutUnit float_offset, | 92 const LayoutUnit float_offset, |
102 const NGBoxStrut& margins, | 93 const NGBoxStrut& margins, |
103 NGExclusion::Type exclusion_type) { | 94 NGExclusion::Type exclusion_type) { |
104 NGExclusion exclusion; | 95 NGExclusion exclusion; |
105 exclusion.type = exclusion_type; | 96 exclusion.type = exclusion_type; |
106 NGLogicalRect& rect = exclusion.rect; | 97 NGLogicalRect& rect = exclusion.rect; |
107 rect.offset = opportunity.offset; | 98 rect.offset = opportunity.offset; |
108 rect.offset.inline_offset += float_offset; | 99 rect.offset.inline_offset += float_offset; |
109 | 100 |
110 rect.size.inline_size = fragment.InlineSize() + margins.InlineSum(); | 101 rect.size.inline_size = fragment.InlineSize() + margins.InlineSum(); |
111 rect.size.block_size = fragment.BlockSize() + margins.BlockSum(); | 102 rect.size.block_size = fragment.BlockSize() + margins.BlockSum(); |
112 return exclusion; | 103 return exclusion; |
113 } | 104 } |
114 | 105 |
115 // Updates the Floating Object's left offset from the provided parent_space | 106 // Updates the Floating Object's left offset from the provided parent_space |
116 // and {@code floating_object}'s space and margins. | 107 // and {@code floating_object}'s space and margins. |
117 void UpdateFloatingObjectLeftOffset(const NGConstraintSpace& new_parent_space, | 108 void UpdateFloatingObjectLeftOffset(const NGConstraintSpace& new_parent_space, |
118 const NGLogicalOffset& float_logical_offset, | 109 const NGLogicalOffset& float_logical_offset, |
119 NGFloatingObject* floating_object) { | 110 NGFloatingObject* floating_object) { |
120 DCHECK(floating_object); | 111 DCHECK(floating_object); |
121 // TODO(glebl): We should use physical offset here. | 112 // TODO(glebl): We should use physical offset here. |
122 floating_object->left_offset = | 113 floating_object->left_offset = floating_object->from_offset.inline_offset - |
123 floating_object->original_parent_space->BfcOffset().inline_offset - | 114 new_parent_space.BfcOffset().inline_offset + |
124 new_parent_space.BfcOffset().inline_offset + | 115 float_logical_offset.inline_offset; |
125 float_logical_offset.inline_offset; | |
126 } | 116 } |
127 } // namespace | 117 } // namespace |
128 | 118 |
129 // Calculates the relative position from {@code from_offset} of the | 119 NGLogicalOffset PositionFloat(NGFloatingObject* floating_object, |
130 // floating object that is requested to be positioned from {@code origin_point}. | |
131 NGLogicalOffset PositionFloat(const NGLogicalOffset& origin_point, | |
132 const NGLogicalOffset& from_offset, | |
133 NGFloatingObject* floating_object, | |
134 NGConstraintSpace* new_parent_space) { | 120 NGConstraintSpace* new_parent_space) { |
135 DCHECK(floating_object); | 121 DCHECK(floating_object); |
136 const auto* float_space = floating_object->space.get(); | |
137 DCHECK(floating_object->fragment) << "Fragment cannot be null here"; | 122 DCHECK(floating_object->fragment) << "Fragment cannot be null here"; |
138 | 123 |
139 // TODO(ikilpatrick): The writing mode switching here looks wrong. | 124 // TODO(ikilpatrick): The writing mode switching here looks wrong. |
140 NGBoxFragment float_fragment( | 125 NGBoxFragment float_fragment( |
141 float_space->WritingMode(), | 126 floating_object->writing_mode, |
142 toNGPhysicalBoxFragment(floating_object->fragment.get())); | 127 toNGPhysicalBoxFragment(floating_object->fragment.get())); |
143 | 128 |
144 // Find a layout opportunity that will fit our float. | 129 // Find a layout opportunity that will fit our float. |
145 const NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( | 130 const NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( |
146 new_parent_space, float_fragment, origin_point, floating_object->margins, | 131 new_parent_space, float_fragment, floating_object); |
147 floating_object->available_size); | |
148 DCHECK(!opportunity.IsEmpty()) << "Opportunity is empty but it shouldn't be"; | 132 DCHECK(!opportunity.IsEmpty()) << "Opportunity is empty but it shouldn't be"; |
149 | 133 |
150 // Calculate the float offset if needed. | 134 // Calculate the float offset if needed. |
151 LayoutUnit float_offset; | 135 LayoutUnit float_offset; |
152 if (floating_object->exclusion_type == NGExclusion::kFloatRight) { | 136 if (floating_object->exclusion_type == NGExclusion::kFloatRight) { |
153 LayoutUnit float_margin_box_inline_size = | 137 LayoutUnit float_margin_box_inline_size = |
154 float_fragment.InlineSize() + floating_object->margins.InlineSum(); | 138 float_fragment.InlineSize() + floating_object->margins.InlineSum(); |
155 float_offset = opportunity.size.inline_size - float_margin_box_inline_size; | 139 float_offset = opportunity.size.inline_size - float_margin_box_inline_size; |
156 } | 140 } |
157 | 141 |
158 // Add the float as an exclusion. | 142 // Add the float as an exclusion. |
159 const NGExclusion exclusion = CreateExclusion( | 143 const NGExclusion exclusion = CreateExclusion( |
160 float_fragment, opportunity, float_offset, floating_object->margins, | 144 float_fragment, opportunity, float_offset, floating_object->margins, |
161 floating_object->exclusion_type); | 145 floating_object->exclusion_type); |
162 new_parent_space->AddExclusion(exclusion); | 146 new_parent_space->AddExclusion(exclusion); |
163 | 147 |
164 NGLogicalOffset logical_offset = CalculateLogicalOffsetForOpportunity( | 148 NGLogicalOffset logical_offset = CalculateLogicalOffsetForOpportunity( |
165 opportunity, float_offset, from_offset, floating_object); | 149 opportunity, float_offset, floating_object); |
166 UpdateFloatingObjectLeftOffset(*new_parent_space, logical_offset, | 150 UpdateFloatingObjectLeftOffset(*new_parent_space, logical_offset, |
167 floating_object); | 151 floating_object); |
168 return logical_offset; | 152 return logical_offset; |
169 } | 153 } |
| 154 |
| 155 void PositionPendingFloats(const LayoutUnit& origin_block_offset, |
| 156 NGConstraintSpace* space, |
| 157 NGFragmentBuilder* builder) { |
| 158 DCHECK(builder) << "Builder cannot be null here"; |
| 159 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; |
| 160 LayoutUnit bfc_block_offset = builder->BfcOffset().value().block_offset; |
| 161 |
| 162 for (auto& floating_object : builder->UnpositionedFloats()) { |
| 163 floating_object->origin_offset.block_offset = origin_block_offset; |
| 164 floating_object->from_offset.block_offset = bfc_block_offset; |
| 165 |
| 166 NGLogicalOffset offset = PositionFloat(floating_object.get(), space); |
| 167 builder->AddFloatingObject(floating_object, offset); |
| 168 } |
| 169 builder->MutableUnpositionedFloats().clear(); |
| 170 } |
| 171 |
170 } // namespace blink | 172 } // namespace blink |
OLD | NEW |