| 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/inline/ng_inline_node.h" | 7 #include "core/layout/ng/inline/ng_inline_node.h" |
| 8 #include "core/layout/ng/ng_absolute_utils.h" | 8 #include "core/layout/ng/ng_absolute_utils.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" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 NGLogicalOffset mutable_offset(offset); | 81 NGLogicalOffset mutable_offset(offset); |
| 82 AdjustToClearance(space.ClearanceOffset(), &mutable_offset); | 82 AdjustToClearance(space.ClearanceOffset(), &mutable_offset); |
| 83 builder->SetBfcOffset(mutable_offset); | 83 builder->SetBfcOffset(mutable_offset); |
| 84 } | 84 } |
| 85 } | 85 } |
| 86 | 86 |
| 87 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node, | 87 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node, |
| 88 NGConstraintSpace* space, | 88 NGConstraintSpace* space, |
| 89 NGBlockBreakToken* break_token) | 89 NGBlockBreakToken* break_token) |
| 90 : NGLayoutAlgorithm(node, space, break_token), | 90 : NGLayoutAlgorithm(node, space, break_token), |
| 91 builder_(NGPhysicalFragment::kFragmentBox, node), | |
| 92 space_builder_(constraint_space_) {} | 91 space_builder_(constraint_space_) {} |
| 93 | 92 |
| 94 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() | 93 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() |
| 95 const { | 94 const { |
| 96 MinMaxContentSize sizes; | 95 MinMaxContentSize sizes; |
| 97 | 96 |
| 98 // Size-contained elements don't consider their contents for intrinsic sizing. | 97 // Size-contained elements don't consider their contents for intrinsic sizing. |
| 99 if (Style().ContainsSize()) | 98 if (Style().ContainsSize()) |
| 100 return sizes; | 99 return sizes; |
| 101 | 100 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 129 return sizes; | 128 return sizes; |
| 130 } | 129 } |
| 131 | 130 |
| 132 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( | 131 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( |
| 133 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { | 132 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { |
| 134 LayoutUnit inline_offset = | 133 LayoutUnit inline_offset = |
| 135 border_and_padding_.inline_start + curr_child_margins_.inline_start; | 134 border_and_padding_.inline_start + curr_child_margins_.inline_start; |
| 136 LayoutUnit block_offset = content_size_; | 135 LayoutUnit block_offset = content_size_; |
| 137 if (known_fragment_offset) { | 136 if (known_fragment_offset) { |
| 138 block_offset = known_fragment_offset.value().block_offset - | 137 block_offset = known_fragment_offset.value().block_offset - |
| 139 builder_.BfcOffset().value().block_offset; | 138 ContainerBfcOffset().block_offset; |
| 140 } | 139 } |
| 141 return {inline_offset, block_offset}; | 140 return {inline_offset, block_offset}; |
| 142 } | 141 } |
| 143 | 142 |
| 144 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { | 143 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { |
| 145 WTF::Optional<MinMaxContentSize> min_max_size; | 144 WTF::Optional<MinMaxContentSize> min_max_size; |
| 146 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) | 145 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) |
| 147 min_max_size = ComputeMinMaxContentSize(); | 146 min_max_size = ComputeMinMaxContentSize(); |
| 148 | 147 |
| 149 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + | 148 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + |
| (...skipping 10 matching lines...) Expand all Loading... |
| 160 // borders and padding. | 159 // borders and padding. |
| 161 NGLogicalSize adjusted_size(size); | 160 NGLogicalSize adjusted_size(size); |
| 162 if (size.block_size == NGSizeIndefinite) | 161 if (size.block_size == NGSizeIndefinite) |
| 163 adjusted_size.inline_size -= border_and_padding_.InlineSum(); | 162 adjusted_size.inline_size -= border_and_padding_.InlineSum(); |
| 164 else | 163 else |
| 165 adjusted_size -= border_and_padding_; | 164 adjusted_size -= border_and_padding_; |
| 166 | 165 |
| 167 space_builder_.SetAvailableSize(adjusted_size) | 166 space_builder_.SetAvailableSize(adjusted_size) |
| 168 .SetPercentageResolutionSize(adjusted_size); | 167 .SetPercentageResolutionSize(adjusted_size); |
| 169 | 168 |
| 170 builder_.SetDirection(constraint_space_->Direction()); | 169 container_builder_.SetDirection(constraint_space_->Direction()); |
| 171 builder_.SetWritingMode(constraint_space_->WritingMode()); | 170 container_builder_.SetWritingMode(constraint_space_->WritingMode()); |
| 172 builder_.SetSize(size); | 171 container_builder_.SetSize(size); |
| 173 | 172 |
| 174 NGBlockChildIterator child_iterator(Node()->FirstChild(), BreakToken()); | 173 NGBlockChildIterator child_iterator(Node()->FirstChild(), BreakToken()); |
| 175 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 174 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
| 176 NGLayoutInputNode* child = entry.node; | 175 NGLayoutInputNode* child = entry.node; |
| 177 NGBreakToken* child_break_token = entry.token; | 176 NGBreakToken* child_break_token = entry.token; |
| 178 | 177 |
| 179 // If we are resuming from a break token our start border and padding is | 178 // If we are resuming from a break token our start border and padding is |
| 180 // within a previous fragment. | 179 // within a previous fragment. |
| 181 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; | 180 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; |
| 182 | 181 |
| 183 curr_margin_strut_ = ConstraintSpace().MarginStrut(); | 182 curr_margin_strut_ = ConstraintSpace().MarginStrut(); |
| 184 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); | 183 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); |
| 185 | 184 |
| 186 // Margins collapsing: | 185 // Margins collapsing: |
| 187 // Do not collapse margins between parent and its child if there is | 186 // Do not collapse margins between parent and its child if there is |
| 188 // border/padding between them. | 187 // border/padding between them. |
| 189 if (border_and_padding_.block_start) { | 188 if (border_and_padding_.block_start) { |
| 190 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 189 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 191 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 190 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
| 192 &builder_); | 191 &container_builder_); |
| 193 curr_margin_strut_ = NGMarginStrut(); | 192 curr_margin_strut_ = NGMarginStrut(); |
| 194 } | 193 } |
| 195 | 194 |
| 196 // If a new formatting context hits the if branch above then the BFC offset is | 195 // If a new formatting context hits the if branch above then the BFC offset is |
| 197 // still {} as the margin strut from the constraint space must also be empty. | 196 // still {} as the margin strut from the constraint space must also be empty. |
| 198 if (ConstraintSpace().IsNewFormattingContext()) { | 197 if (ConstraintSpace().IsNewFormattingContext()) { |
| 199 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 198 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
| 200 &builder_); | 199 &container_builder_); |
| 201 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); | 200 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); |
| 202 DCHECK_EQ(builder_.BfcOffset().value(), NGLogicalOffset()); | 201 DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset()); |
| 203 curr_bfc_offset_ = {}; | 202 curr_bfc_offset_ = {}; |
| 204 } | 203 } |
| 205 | 204 |
| 206 curr_bfc_offset_.block_offset += content_size_; | 205 curr_bfc_offset_.block_offset += content_size_; |
| 207 | 206 |
| 208 while (child) { | 207 while (child) { |
| 209 if (child->IsBlock()) { | 208 if (child->IsBlock()) { |
| 210 EPosition position = child->Style().GetPosition(); | 209 EPosition position = child->Style().GetPosition(); |
| 211 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { | 210 if (position == EPosition::kAbsolute || position == EPosition::kFixed) { |
| 212 // TODO(ikilpatrick): curr_margin_strut_ shouldn't be included if there | 211 // TODO(ikilpatrick): curr_margin_strut_ shouldn't be included if there |
| 213 // is no content size yet? See floats-wrap-inside-inline-006. | 212 // is no content size yet? See floats-wrap-inside-inline-006. |
| 214 NGLogicalOffset offset = {border_and_padding_.inline_start, | 213 NGLogicalOffset offset = {border_and_padding_.inline_start, |
| 215 content_size_ + curr_margin_strut_.Sum()}; | 214 content_size_ + curr_margin_strut_.Sum()}; |
| 216 builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), offset); | 215 container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), |
| 216 offset); |
| 217 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 217 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
| 218 child = entry.node; | 218 child = entry.node; |
| 219 child_break_token = entry.token; | 219 child_break_token = entry.token; |
| 220 continue; | 220 continue; |
| 221 } | 221 } |
| 222 } | 222 } |
| 223 | 223 |
| 224 PrepareChildLayout(child); | 224 PrepareChildLayout(child); |
| 225 RefPtr<NGConstraintSpace> child_space = | 225 RefPtr<NGConstraintSpace> child_space = |
| 226 CreateConstraintSpaceForChild(child); | 226 CreateConstraintSpaceForChild(child); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 244 content_size_ += border_and_padding_.block_end; | 244 content_size_ += border_and_padding_.block_end; |
| 245 if (border_and_padding_.block_end || | 245 if (border_and_padding_.block_end || |
| 246 ConstraintSpace().IsNewFormattingContext()) { | 246 ConstraintSpace().IsNewFormattingContext()) { |
| 247 content_size_ += curr_margin_strut_.Sum(); | 247 content_size_ += curr_margin_strut_.Sum(); |
| 248 curr_margin_strut_ = NGMarginStrut(); | 248 curr_margin_strut_ = NGMarginStrut(); |
| 249 } | 249 } |
| 250 | 250 |
| 251 // Recompute the block-axis size now that we know our content size. | 251 // Recompute the block-axis size now that we know our content size. |
| 252 size.block_size = | 252 size.block_size = |
| 253 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 253 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
| 254 builder_.SetBlockSize(size.block_size); | 254 container_builder_.SetBlockSize(size.block_size); |
| 255 | 255 |
| 256 // Layout our absolute and fixed positioned children. | 256 // Layout our absolute and fixed positioned children. |
| 257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &builder_).Run(); | 257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run(); |
| 258 | 258 |
| 259 // Non-empty blocks always know their position in space: | 259 // Non-empty blocks always know their position in space: |
| 260 if (size.block_size) { | 260 if (size.block_size) { |
| 261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
| 263 &builder_); | 263 &container_builder_); |
| 264 PositionPendingFloats(curr_bfc_offset_.block_offset, | 264 PositionPendingFloats(curr_bfc_offset_.block_offset, |
| 265 MutableConstraintSpace(), &builder_); | 265 MutableConstraintSpace(), &container_builder_); |
| 266 } | 266 } |
| 267 | 267 |
| 268 // Margins collapsing: | 268 // Margins collapsing: |
| 269 // Do not collapse margins between the last in-flow child and bottom margin | 269 // Do not collapse margins between the last in-flow child and bottom margin |
| 270 // of its parent if the parent has height != auto() | 270 // of its parent if the parent has height != auto() |
| 271 if (!Style().LogicalHeight().IsAuto()) { | 271 if (!Style().LogicalHeight().IsAuto()) { |
| 272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. | 272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. |
| 273 curr_margin_strut_ = NGMarginStrut(); | 273 curr_margin_strut_ = NGMarginStrut(); |
| 274 } | 274 } |
| 275 builder_.SetEndMarginStrut(curr_margin_strut_); | 275 container_builder_.SetEndMarginStrut(curr_margin_strut_); |
| 276 | 276 |
| 277 builder_.SetOverflowSize(NGLogicalSize(max_inline_size_, content_size_)); | 277 container_builder_.SetOverflowSize( |
| 278 NGLogicalSize(max_inline_size_, content_size_)); |
| 278 | 279 |
| 279 if (ConstraintSpace().HasBlockFragmentation()) | 280 if (ConstraintSpace().HasBlockFragmentation()) |
| 280 FinalizeForFragmentation(); | 281 FinalizeForFragmentation(); |
| 281 | 282 |
| 282 return builder_.ToBoxFragment(); | 283 return container_builder_.ToBoxFragment(); |
| 283 } | 284 } |
| 284 | 285 |
| 285 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { | 286 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { |
| 286 DCHECK(child); | 287 DCHECK(child); |
| 287 | 288 |
| 288 // Calculate margins in parent's writing mode. | 289 // Calculate margins in parent's writing mode. |
| 289 curr_child_margins_ = CalculateMargins( | 290 curr_child_margins_ = CalculateMargins( |
| 290 child, *space_builder_.ToConstraintSpace( | 291 child, *space_builder_.ToConstraintSpace( |
| 291 FromPlatformWritingMode(Style().GetWritingMode()))); | 292 FromPlatformWritingMode(Style().GetWritingMode()))); |
| 292 | 293 |
| 293 // Set estimated BFC offset to the next child's constraint space. | 294 // Set estimated BFC offset to the next child's constraint space. |
| 294 curr_bfc_offset_ = builder_.BfcOffset() ? builder_.BfcOffset().value() | 295 curr_bfc_offset_ = container_builder_.BfcOffset() |
| 295 : ConstraintSpace().BfcOffset(); | 296 ? container_builder_.BfcOffset().value() |
| 297 : ConstraintSpace().BfcOffset(); |
| 296 curr_bfc_offset_.block_offset += content_size_; | 298 curr_bfc_offset_.block_offset += content_size_; |
| 297 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 299 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
| 298 | 300 |
| 299 bool is_floating = child->IsBlock() && child->Style().IsFloating(); | 301 bool is_floating = child->IsBlock() && child->Style().IsFloating(); |
| 300 | 302 |
| 301 bool should_position_pending_floats = | 303 bool should_position_pending_floats = |
| 302 child->IsBlock() && !is_floating && | 304 child->IsBlock() && !is_floating && |
| 303 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && | 305 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && |
| 304 ClearanceMayAffectLayout(ConstraintSpace(), builder_.UnpositionedFloats(), | 306 ClearanceMayAffectLayout(ConstraintSpace(), |
| 307 container_builder_.UnpositionedFloats(), |
| 305 child->Style()); | 308 child->Style()); |
| 306 | 309 |
| 307 // Children which may clear a float need to force all the pending floats to | 310 // Children which may clear a float need to force all the pending floats to |
| 308 // be positioned before layout. This also resolves the fragment's bfc offset. | 311 // be positioned before layout. This also resolves the fragment's bfc offset. |
| 309 if (should_position_pending_floats) { | 312 if (should_position_pending_floats) { |
| 310 LayoutUnit origin_point_block_offset = | 313 LayoutUnit origin_point_block_offset = |
| 311 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); | 314 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); |
| 312 MaybeUpdateFragmentBfcOffset( | 315 MaybeUpdateFragmentBfcOffset( |
| 313 ConstraintSpace(), | 316 ConstraintSpace(), |
| 314 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, &builder_); | 317 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, |
| 318 &container_builder_); |
| 315 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), | 319 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), |
| 316 &builder_); | 320 &container_builder_); |
| 317 } | 321 } |
| 318 | 322 |
| 319 bool is_inflow = child->IsInline() || !is_floating; | 323 bool is_inflow = child->IsInline() || !is_floating; |
| 320 | 324 |
| 321 // Only inflow children (e.g. not floats) are included in the child's margin | 325 // Only inflow children (e.g. not floats) are included in the child's margin |
| 322 // strut as they do not participate in margin collapsing. | 326 // strut as they do not participate in margin collapsing. |
| 323 if (is_inflow) { | 327 if (is_inflow) { |
| 324 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 328 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
| 325 // Append the current margin strut with child's block start margin. | 329 // Append the current margin strut with child's block start margin. |
| 326 // Non empty border/padding use cases are handled inside of the child's | 330 // Non empty border/padding use cases are handled inside of the child's |
| (...skipping 11 matching lines...) Expand all Loading... |
| 338 child->IsInline() || | 342 child->IsInline() || |
| 339 (!is_floating && | 343 (!is_floating && |
| 340 IsNewFormattingContextForBlockLevelChild(Style(), *child)); | 344 IsNewFormattingContextForBlockLevelChild(Style(), *child)); |
| 341 | 345 |
| 342 // Inline children or children which establish a block formatting context | 346 // Inline children or children which establish a block formatting context |
| 343 // collapse margins and position themselves immediately as they need to know | 347 // collapse margins and position themselves immediately as they need to know |
| 344 // their BFC offset for fragmentation purposes. | 348 // their BFC offset for fragmentation purposes. |
| 345 if (should_collapse_margins) { | 349 if (should_collapse_margins) { |
| 346 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 350 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
| 347 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 351 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
| 348 &builder_); | 352 &container_builder_); |
| 349 PositionPendingFloats(curr_bfc_offset_.block_offset, | 353 PositionPendingFloats(curr_bfc_offset_.block_offset, |
| 350 MutableConstraintSpace(), &builder_); | 354 MutableConstraintSpace(), &container_builder_); |
| 351 curr_margin_strut_ = {}; | 355 curr_margin_strut_ = {}; |
| 352 } | 356 } |
| 353 } | 357 } |
| 354 | 358 |
| 355 void NGBlockLayoutAlgorithm::FinishChildLayout( | 359 void NGBlockLayoutAlgorithm::FinishChildLayout( |
| 356 NGLayoutInputNode* child, | 360 NGLayoutInputNode* child, |
| 357 NGConstraintSpace* child_space, | 361 NGConstraintSpace* child_space, |
| 358 RefPtr<NGLayoutResult> layout_result) { | 362 RefPtr<NGLayoutResult> layout_result) { |
| 359 NGBoxFragment fragment( | 363 NGBoxFragment fragment( |
| 360 ConstraintSpace().WritingMode(), | 364 ConstraintSpace().WritingMode(), |
| 361 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); | 365 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); |
| 362 | 366 |
| 363 // Pull out unpositioned floats to the current fragment. This may needed if | 367 // Pull out unpositioned floats to the current fragment. This may needed if |
| 364 // for example the child fragment could not position its floats because it's | 368 // for example the child fragment could not position its floats because it's |
| 365 // empty and therefore couldn't determine its position in space. | 369 // empty and therefore couldn't determine its position in space. |
| 366 builder_.MutableUnpositionedFloats().AppendVector( | 370 container_builder_.MutableUnpositionedFloats().AppendVector( |
| 367 layout_result->UnpositionedFloats()); | 371 layout_result->UnpositionedFloats()); |
| 368 | 372 |
| 369 if (child->IsBlock() && child->Style().IsFloating()) { | 373 if (child->IsBlock() && child->Style().IsFloating()) { |
| 370 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); | 374 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); |
| 371 origin_offset.inline_offset += border_and_padding_.inline_start; | 375 origin_offset.inline_offset += border_and_padding_.inline_start; |
| 372 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( | 376 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( |
| 373 child->Style(), child_space->WritingMode(), | 377 child->Style(), child_space->WritingMode(), |
| 374 child_space->AvailableSize(), origin_offset, | 378 child_space->AvailableSize(), origin_offset, |
| 375 constraint_space_->BfcOffset(), curr_child_margins_, | 379 constraint_space_->BfcOffset(), curr_child_margins_, |
| 376 layout_result->PhysicalFragment().Get()); | 380 layout_result->PhysicalFragment().Get()); |
| 377 builder_.AddUnpositionedFloat(floating_object); | 381 container_builder_.AddUnpositionedFloat(floating_object); |
| 378 // No need to postpone the positioning if we know the correct offset. | 382 // No need to postpone the positioning if we know the correct offset. |
| 379 if (builder_.BfcOffset()) { | 383 if (container_builder_.BfcOffset()) { |
| 380 NGLogicalOffset origin_point = curr_bfc_offset_; | 384 NGLogicalOffset origin_point = curr_bfc_offset_; |
| 381 // Adjust origin point to the margins of the last child. | 385 // Adjust origin point to the margins of the last child. |
| 382 // Example: <div style="margin-bottom: 20px"><float></div> | 386 // Example: <div style="margin-bottom: 20px"><float></div> |
| 383 // <div style="margin-bottom: 30px"></div> | 387 // <div style="margin-bottom: 30px"></div> |
| 384 origin_point.block_offset += curr_margin_strut_.Sum(); | 388 origin_point.block_offset += curr_margin_strut_.Sum(); |
| 385 PositionPendingFloats(origin_point.block_offset, MutableConstraintSpace(), | 389 PositionPendingFloats(origin_point.block_offset, MutableConstraintSpace(), |
| 386 &builder_); | 390 &container_builder_); |
| 387 } | 391 } |
| 388 return; | 392 return; |
| 389 } | 393 } |
| 390 | 394 |
| 391 // Determine the fragment's position in the parent space either by using | 395 // Determine the fragment's position in the parent space either by using |
| 392 // content_size_ or known fragment's BFC offset. | 396 // content_size_ or known fragment's BFC offset. |
| 393 WTF::Optional<NGLogicalOffset> bfc_offset; | 397 WTF::Optional<NGLogicalOffset> bfc_offset; |
| 394 if (child_space->IsNewFormattingContext()) { | 398 if (child_space->IsNewFormattingContext()) { |
| 395 DCHECK(builder_.BfcOffset()); | |
| 396 bfc_offset = curr_bfc_offset_; | 399 bfc_offset = curr_bfc_offset_; |
| 397 } else if (fragment.BfcOffset()) { | 400 } else if (fragment.BfcOffset()) { |
| 398 // Fragment that knows its offset can be used to set parent's BFC position. | 401 // Fragment that knows its offset can be used to set parent's BFC position. |
| 399 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 402 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
| 400 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 403 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
| 401 &builder_); | 404 &container_builder_); |
| 402 PositionPendingFloats(curr_bfc_offset_.block_offset, | 405 PositionPendingFloats(curr_bfc_offset_.block_offset, |
| 403 MutableConstraintSpace(), &builder_); | 406 MutableConstraintSpace(), &container_builder_); |
| 404 bfc_offset = curr_bfc_offset_; | 407 bfc_offset = curr_bfc_offset_; |
| 405 } else if (builder_.BfcOffset()) { | 408 } else if (container_builder_.BfcOffset()) { |
| 406 // Fragment doesn't know its offset but we can still calculate its BFC | 409 // Fragment doesn't know its offset but we can still calculate its BFC |
| 407 // position because the parent fragment's BFC is known. | 410 // position because the parent fragment's BFC is known. |
| 408 // Example: | 411 // Example: |
| 409 // BFC Offset is known here because of the padding. | 412 // BFC Offset is known here because of the padding. |
| 410 // <div style="padding: 1px"> | 413 // <div style="padding: 1px"> |
| 411 // <div id="empty-div" style="margins: 1px"></div> | 414 // <div id="empty-div" style="margins: 1px"></div> |
| 412 bfc_offset = curr_bfc_offset_; | 415 bfc_offset = curr_bfc_offset_; |
| 413 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); | 416 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); |
| 414 } | 417 } |
| 415 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | 418 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
| 416 | 419 |
| 417 // Update margin strut. | 420 // Update margin strut. |
| 418 curr_margin_strut_ = fragment.EndMarginStrut(); | 421 curr_margin_strut_ = fragment.EndMarginStrut(); |
| 419 curr_margin_strut_.Append(curr_child_margins_.block_end); | 422 curr_margin_strut_.Append(curr_child_margins_.block_end); |
| 420 | 423 |
| 421 // Only modify content_size if BlockSize is not empty. It's needed to prevent | 424 // Only modify content_size if BlockSize is not empty. It's needed to prevent |
| 422 // the situation when logical_offset is included in content_size for empty | 425 // the situation when logical_offset is included in content_size for empty |
| 423 // blocks. Example: | 426 // blocks. Example: |
| 424 // <div style="overflow:hidden"> | 427 // <div style="overflow:hidden"> |
| 425 // <div style="margin-top: 8px"></div> | 428 // <div style="margin-top: 8px"></div> |
| 426 // <div style="margin-top: 10px"></div> | 429 // <div style="margin-top: 10px"></div> |
| 427 // </div> | 430 // </div> |
| 428 if (fragment.BlockSize()) | 431 if (fragment.BlockSize()) |
| 429 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | 432 content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
| 430 max_inline_size_ = | 433 max_inline_size_ = |
| 431 std::max(max_inline_size_, fragment.InlineSize() + | 434 std::max(max_inline_size_, fragment.InlineSize() + |
| 432 curr_child_margins_.InlineSum() + | 435 curr_child_margins_.InlineSum() + |
| 433 border_and_padding_.InlineSum()); | 436 border_and_padding_.InlineSum()); |
| 434 | 437 |
| 435 builder_.AddChild(layout_result, logical_offset); | 438 container_builder_.AddChild(layout_result, logical_offset); |
| 436 } | 439 } |
| 437 | 440 |
| 438 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { | 441 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { |
| 439 LayoutUnit used_block_size = | 442 LayoutUnit used_block_size = |
| 440 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); | 443 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); |
| 441 LayoutUnit block_size = ComputeBlockSizeForFragment( | 444 LayoutUnit block_size = ComputeBlockSizeForFragment( |
| 442 ConstraintSpace(), Style(), used_block_size + content_size_); | 445 ConstraintSpace(), Style(), used_block_size + content_size_); |
| 443 | 446 |
| 444 block_size -= used_block_size; | 447 block_size -= used_block_size; |
| 445 DCHECK_GE(block_size, LayoutUnit()) | 448 DCHECK_GE(block_size, LayoutUnit()) |
| 446 << "Adding and subtracting the used_block_size shouldn't leave the " | 449 << "Adding and subtracting the used_block_size shouldn't leave the " |
| 447 "block_size for this fragment smaller than zero."; | 450 "block_size for this fragment smaller than zero."; |
| 448 | 451 |
| 449 DCHECK(builder_.BfcOffset()) << "We must have our BfcOffset by this point " | |
| 450 "to determine the space left in the flow."; | |
| 451 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - | 452 LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() - |
| 452 builder_.BfcOffset().value().block_offset; | 453 ContainerBfcOffset().block_offset; |
| 453 DCHECK_GE(space_left, LayoutUnit()); | 454 DCHECK_GE(space_left, LayoutUnit()); |
| 454 | 455 |
| 455 if (builder_.DidBreak()) { | 456 if (container_builder_.DidBreak()) { |
| 456 // One of our children broke. Even if we fit within the remaining space we | 457 // One of our children broke. Even if we fit within the remaining space we |
| 457 // need to prepare a break token. | 458 // need to prepare a break token. |
| 458 builder_.SetUsedBlockSize(std::min(space_left, block_size) + | 459 container_builder_.SetUsedBlockSize(std::min(space_left, block_size) + |
| 459 used_block_size); | 460 used_block_size); |
| 460 builder_.SetBlockSize(std::min(space_left, block_size)); | 461 container_builder_.SetBlockSize(std::min(space_left, block_size)); |
| 461 builder_.SetBlockOverflow(space_left); | 462 container_builder_.SetBlockOverflow(space_left); |
| 462 return; | 463 return; |
| 463 } | 464 } |
| 464 | 465 |
| 465 if (block_size > space_left) { | 466 if (block_size > space_left) { |
| 466 // Need a break inside this block. | 467 // Need a break inside this block. |
| 467 builder_.SetUsedBlockSize(space_left + used_block_size); | 468 container_builder_.SetUsedBlockSize(space_left + used_block_size); |
| 468 builder_.SetBlockSize(space_left); | 469 container_builder_.SetBlockSize(space_left); |
| 469 builder_.SetBlockOverflow(space_left); | 470 container_builder_.SetBlockOverflow(space_left); |
| 470 return; | 471 return; |
| 471 } | 472 } |
| 472 | 473 |
| 473 // The end of the block fits in the current fragmentainer. | 474 // The end of the block fits in the current fragmentainer. |
| 474 builder_.SetBlockSize(block_size); | 475 container_builder_.SetBlockSize(block_size); |
| 475 builder_.SetBlockOverflow(content_size_); | 476 container_builder_.SetBlockOverflow(content_size_); |
| 476 } | 477 } |
| 477 | 478 |
| 478 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( | 479 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( |
| 479 NGLayoutInputNode* child, | 480 NGLayoutInputNode* child, |
| 480 const NGConstraintSpace& space) { | 481 const NGConstraintSpace& space) { |
| 481 DCHECK(child); | 482 DCHECK(child); |
| 482 const ComputedStyle& child_style = child->Style(); | 483 const ComputedStyle& child_style = child->Style(); |
| 483 | 484 |
| 484 WTF::Optional<MinMaxContentSize> sizes; | 485 WTF::Optional<MinMaxContentSize> sizes; |
| 485 if (NeedMinMaxContentSize(space, child_style)) | 486 if (NeedMinMaxContentSize(space, child_style)) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 space_builder_.SetMarginStrut(child_style.IsFloating() ? NGMarginStrut() | 525 space_builder_.SetMarginStrut(child_style.IsFloating() ? NGMarginStrut() |
| 525 : curr_margin_strut_); | 526 : curr_margin_strut_); |
| 526 | 527 |
| 527 LayoutUnit space_available; | 528 LayoutUnit space_available; |
| 528 if (constraint_space_->HasBlockFragmentation()) { | 529 if (constraint_space_->HasBlockFragmentation()) { |
| 529 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); | 530 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); |
| 530 // If a block establishes a new formatting context we must know our | 531 // If a block establishes a new formatting context we must know our |
| 531 // position in the formatting context, and are able to adjust the | 532 // position in the formatting context, and are able to adjust the |
| 532 // fragmentation line. | 533 // fragmentation line. |
| 533 if (is_new_bfc) { | 534 if (is_new_bfc) { |
| 534 DCHECK(builder_.BfcOffset()); | |
| 535 space_available -= curr_bfc_offset_.block_offset; | 535 space_available -= curr_bfc_offset_.block_offset; |
| 536 } | 536 } |
| 537 } | 537 } |
| 538 space_builder_.SetFragmentainerSpaceAvailable(space_available); | 538 space_builder_.SetFragmentainerSpaceAvailable(space_available); |
| 539 | 539 |
| 540 return space_builder_.ToConstraintSpace( | 540 return space_builder_.ToConstraintSpace( |
| 541 FromPlatformWritingMode(child_style.GetWritingMode())); | 541 FromPlatformWritingMode(child_style.GetWritingMode())); |
| 542 } | 542 } |
| 543 } // namespace blink | 543 } // namespace blink |
| OLD | NEW |