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_box_fragment.h" | 9 #include "core/layout/ng/ng_box_fragment.h" |
10 #include "core/layout/ng/ng_column_mapper.h" | 10 #include "core/layout/ng/ng_column_mapper.h" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 } | 177 } |
178 | 178 |
179 } // namespace | 179 } // namespace |
180 | 180 |
181 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( | 181 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( |
182 PassRefPtr<const ComputedStyle> style, | 182 PassRefPtr<const ComputedStyle> style, |
183 NGBlockNode* first_child, | 183 NGBlockNode* first_child, |
184 NGConstraintSpace* constraint_space, | 184 NGConstraintSpace* constraint_space, |
185 NGBreakToken* break_token) | 185 NGBreakToken* break_token) |
186 : NGLayoutAlgorithm(kBlockLayoutAlgorithm), | 186 : NGLayoutAlgorithm(kBlockLayoutAlgorithm), |
187 layout_state_(kStateInit), | |
188 style_(style), | 187 style_(style), |
189 first_child_(first_child), | 188 first_child_(first_child), |
190 constraint_space_(constraint_space), | 189 constraint_space_(constraint_space), |
191 break_token_(break_token), | 190 break_token_(break_token), |
192 is_fragment_margin_strut_block_start_updated_(false) { | 191 is_fragment_margin_strut_block_start_updated_(false) { |
193 DCHECK(style_); | 192 DCHECK(style_); |
194 } | 193 } |
195 | 194 |
196 bool NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes( | 195 bool NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes( |
197 MinAndMaxContentSizes* sizes) { | 196 MinAndMaxContentSizes* sizes) { |
(...skipping 19 matching lines...) Expand all Loading... |
217 } | 216 } |
218 | 217 |
219 sizes->max_content = std::max(sizes->min_content, sizes->max_content); | 218 sizes->max_content = std::max(sizes->min_content, sizes->max_content); |
220 return true; | 219 return true; |
221 } | 220 } |
222 | 221 |
223 NGLayoutStatus NGBlockLayoutAlgorithm::Layout( | 222 NGLayoutStatus NGBlockLayoutAlgorithm::Layout( |
224 NGPhysicalFragment* child_fragment, | 223 NGPhysicalFragment* child_fragment, |
225 NGPhysicalFragment** fragment_out, | 224 NGPhysicalFragment** fragment_out, |
226 NGLayoutAlgorithm** algorithm_out) { | 225 NGLayoutAlgorithm** algorithm_out) { |
227 switch (layout_state_) { | 226 WTF::Optional<MinAndMaxContentSizes> sizes; |
228 case kStateInit: { | 227 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) { |
229 WTF::Optional<MinAndMaxContentSizes> sizes; | 228 // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return |
230 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) { | 229 // MinAndMaxContentSizes. |
231 sizes = MinAndMaxContentSizes(); | 230 sizes = MinAndMaxContentSizes(); |
232 ComputeMinAndMaxContentSizes(&*sizes); | 231 ComputeMinAndMaxContentSizes(&*sizes); |
233 } | 232 } |
234 | 233 |
235 border_and_padding_ = | 234 border_and_padding_ = |
236 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); | 235 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); |
237 | 236 |
238 LayoutUnit inline_size = | 237 LayoutUnit inline_size = |
239 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); | 238 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); |
240 LayoutUnit adjusted_inline_size = | 239 LayoutUnit adjusted_inline_size = |
241 inline_size - border_and_padding_.InlineSum(); | 240 inline_size - border_and_padding_.InlineSum(); |
242 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of | 241 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of |
243 // -1? | 242 // -1? |
244 LayoutUnit block_size = ComputeBlockSizeForFragment( | 243 LayoutUnit block_size = |
245 ConstraintSpace(), Style(), NGSizeIndefinite); | 244 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite); |
246 LayoutUnit adjusted_block_size(block_size); | 245 LayoutUnit adjusted_block_size(block_size); |
247 // Our calculated block-axis size may be indefinite at this point. | 246 // Our calculated block-axis size may be indefinite at this point. |
248 // If so, just leave the size as NGSizeIndefinite instead of subtracting | 247 // If so, just leave the size as NGSizeIndefinite instead of subtracting |
249 // borders and padding. | 248 // borders and padding. |
250 if (adjusted_block_size != NGSizeIndefinite) | 249 if (adjusted_block_size != NGSizeIndefinite) |
251 adjusted_block_size -= border_and_padding_.BlockSum(); | 250 adjusted_block_size -= border_and_padding_.BlockSum(); |
252 | 251 |
253 space_builder_ = new NGConstraintSpaceBuilder(constraint_space_); | 252 space_builder_ = new NGConstraintSpaceBuilder(constraint_space_); |
254 if (Style().specifiesColumns()) { | 253 if (Style().specifiesColumns()) { |
255 space_builder_->SetFragmentationType(kFragmentColumn); | 254 space_builder_->SetFragmentationType(kFragmentColumn); |
256 adjusted_inline_size = | 255 adjusted_inline_size = |
257 ResolveUsedColumnInlineSize(adjusted_inline_size, Style()); | 256 ResolveUsedColumnInlineSize(adjusted_inline_size, Style()); |
258 LayoutUnit inline_progression = | 257 LayoutUnit inline_progression = |
259 adjusted_inline_size + ResolveUsedColumnGap(Style()); | 258 adjusted_inline_size + ResolveUsedColumnGap(Style()); |
260 fragmentainer_mapper_ = | 259 fragmentainer_mapper_ = |
261 new NGColumnMapper(inline_progression, adjusted_block_size); | 260 new NGColumnMapper(inline_progression, adjusted_block_size); |
262 } | 261 } |
263 space_builder_->SetAvailableSize( | 262 space_builder_->SetAvailableSize( |
264 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | 263 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
265 space_builder_->SetPercentageResolutionSize( | 264 space_builder_->SetPercentageResolutionSize( |
266 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | 265 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
267 | 266 |
268 builder_ = new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox); | 267 builder_ = new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox); |
269 builder_->SetDirection(constraint_space_->Direction()); | 268 builder_->SetDirection(constraint_space_->Direction()); |
270 builder_->SetWritingMode(constraint_space_->WritingMode()); | 269 builder_->SetWritingMode(constraint_space_->WritingMode()); |
271 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); | 270 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); |
272 | 271 |
273 if (NGBlockBreakToken* token = CurrentBlockBreakToken()) { | 272 if (NGBlockBreakToken* token = CurrentBlockBreakToken()) { |
274 // Resume after a previous break. | 273 // Resume after a previous break. |
275 content_size_ = token->BreakOffset(); | 274 content_size_ = token->BreakOffset(); |
276 current_child_ = token->InputNode(); | 275 current_child_ = token->InputNode(); |
277 } else { | 276 } else { |
278 content_size_ = border_and_padding_.block_start; | 277 content_size_ = border_and_padding_.block_start; |
279 current_child_ = first_child_; | 278 current_child_ = first_child_; |
280 } | 279 } |
281 | 280 |
282 layout_state_ = kStatePrepareForChildLayout; | 281 while (current_child_) { |
283 return kNotFinished; | 282 EPosition position = current_child_->Style()->position(); |
| 283 if (position == AbsolutePosition || position == FixedPosition) { |
| 284 builder_->AddOutOfFlowChildCandidate(current_child_, |
| 285 GetChildSpaceOffset()); |
| 286 current_child_ = current_child_->NextSibling(); |
| 287 continue; |
284 } | 288 } |
285 case kStatePrepareForChildLayout: { | |
286 if (current_child_) { | |
287 EPosition position = current_child_->Style()->position(); | |
288 if ((position == AbsolutePosition || position == FixedPosition)) { | |
289 builder_->AddOutOfFlowChildCandidate(current_child_, | |
290 GetChildSpaceOffset()); | |
291 current_child_ = current_child_->NextSibling(); | |
292 return kNotFinished; | |
293 } | |
294 DCHECK(!ConstraintSpace().HasBlockFragmentation() || | |
295 SpaceAvailableForCurrentChild() > LayoutUnit()); | |
296 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); | |
297 *algorithm_out = NGLayoutInputNode::AlgorithmForInputNode( | |
298 current_child_, space_for_current_child_); | |
299 layout_state_ = kStateChildLayout; | |
300 return kChildAlgorithmRequired; | |
301 } | |
302 | 289 |
303 // Prepare for kStateOutOfFlowLayout | 290 DCHECK(!ConstraintSpace().HasBlockFragmentation() || |
304 content_size_ += border_and_padding_.block_end; | 291 SpaceAvailableForCurrentChild() > LayoutUnit()); |
| 292 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); |
305 | 293 |
306 // Recompute the block-axis size now that we know our content size. | 294 NGFragment* fragment; |
307 LayoutUnit block_size = ComputeBlockSizeForFragment( | 295 current_child_->LayoutSync(space_for_current_child_, &fragment); |
308 ConstraintSpace(), Style(), content_size_); | 296 NGPhysicalFragment* child_fragment = fragment->PhysicalFragment(); |
309 builder_->SetBlockSize(block_size); | |
310 | 297 |
311 // Out of flow setup. | 298 // TODO(layout_ng): Seems like a giant hack to call this here. |
312 out_of_flow_layout_ = | 299 current_child_->UpdateLayoutBox(toNGPhysicalBoxFragment(child_fragment), |
313 new NGOutOfFlowLayoutPart(&Style(), builder_->Size()); | 300 space_for_current_child_); |
314 builder_->GetAndClearOutOfFlowDescendantCandidates( | |
315 &out_of_flow_candidates_, &out_of_flow_candidate_positions_); | |
316 out_of_flow_candidate_positions_index_ = 0; | |
317 current_child_ = nullptr; | |
318 layout_state_ = kStateOutOfFlowLayout; | |
319 return kNotFinished; | |
320 } | |
321 case kStateChildLayout: { | |
322 DCHECK(current_child_); | |
323 DCHECK(child_fragment); | |
324 | 301 |
325 // TODO(layout_ng): Seems like a giant hack to call this here. | 302 FinishCurrentChildLayout(new NGBoxFragment( |
326 current_child_->UpdateLayoutBox(toNGPhysicalBoxFragment(child_fragment), | 303 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), |
327 space_for_current_child_); | 304 toNGPhysicalBoxFragment(child_fragment))); |
328 | 305 |
329 FinishCurrentChildLayout(new NGBoxFragment( | 306 if (!ProceedToNextUnfinishedSibling(child_fragment)) |
330 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), | 307 break; |
331 toNGPhysicalBoxFragment(child_fragment))); | 308 } |
332 | 309 |
333 if (ProceedToNextUnfinishedSibling(child_fragment)) | 310 content_size_ += border_and_padding_.block_end; |
334 layout_state_ = kStatePrepareForChildLayout; | |
335 else | |
336 layout_state_ = kStateFinalize; | |
337 return kNotFinished; | |
338 } | |
339 case kStateOutOfFlowLayout: | |
340 if (LayoutOutOfFlowChild()) | |
341 layout_state_ = kStateFinalize; | |
342 return kNotFinished; | |
343 case kStateFinalize: { | |
344 builder_->SetInlineOverflow(max_inline_size_) | |
345 .SetBlockOverflow(content_size_); | |
346 | 311 |
347 if (ConstraintSpace().HasBlockFragmentation()) | 312 // Recompute the block-axis size now that we know our content size. |
348 FinalizeForFragmentation(); | 313 block_size = |
| 314 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
| 315 builder_->SetBlockSize(block_size); |
349 | 316 |
350 *fragment_out = builder_->ToBoxFragment(); | 317 // Out of flow setup. |
351 layout_state_ = kStateInit; | 318 out_of_flow_layout_ = new NGOutOfFlowLayoutPart(&Style(), builder_->Size()); |
352 return kNewFragment; | 319 builder_->GetAndClearOutOfFlowDescendantCandidates( |
353 } | 320 &out_of_flow_candidates_, &out_of_flow_candidate_positions_); |
354 }; | 321 out_of_flow_candidate_positions_index_ = 0; |
355 NOTREACHED(); | 322 current_child_ = nullptr; |
356 *fragment_out = nullptr; | 323 |
| 324 while (!LayoutOutOfFlowChild()) |
| 325 continue; |
| 326 |
| 327 builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); |
| 328 |
| 329 if (ConstraintSpace().HasBlockFragmentation()) |
| 330 FinalizeForFragmentation(); |
| 331 |
| 332 *fragment_out = builder_->ToBoxFragment(); |
357 return kNewFragment; | 333 return kNewFragment; |
358 } | 334 } |
359 | 335 |
360 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout(NGFragment* fragment) { | 336 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout(NGFragment* fragment) { |
361 NGBoxStrut child_margins = ComputeMargins( | 337 NGBoxStrut child_margins = ComputeMargins( |
362 *space_for_current_child_, CurrentChildStyle(), | 338 *space_for_current_child_, CurrentChildStyle(), |
363 constraint_space_->WritingMode(), constraint_space_->Direction()); | 339 constraint_space_->WritingMode(), constraint_space_->Direction()); |
364 | 340 |
365 NGLogicalOffset fragment_offset; | 341 NGLogicalOffset fragment_offset; |
366 if (CurrentChildStyle().isFloating()) { | 342 if (CurrentChildStyle().isFloating()) { |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 visitor->trace(builder_); | 678 visitor->trace(builder_); |
703 visitor->trace(space_builder_); | 679 visitor->trace(space_builder_); |
704 visitor->trace(space_for_current_child_); | 680 visitor->trace(space_for_current_child_); |
705 visitor->trace(current_child_); | 681 visitor->trace(current_child_); |
706 visitor->trace(out_of_flow_layout_); | 682 visitor->trace(out_of_flow_layout_); |
707 visitor->trace(out_of_flow_candidates_); | 683 visitor->trace(out_of_flow_candidates_); |
708 visitor->trace(fragmentainer_mapper_); | 684 visitor->trace(fragmentainer_mapper_); |
709 } | 685 } |
710 | 686 |
711 } // namespace blink | 687 } // namespace blink |
OLD | NEW |